mirror of
https://github.com/ProtonMail/proton-bridge.git
synced 2025-12-10 04:36:43 +00:00
Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f9ac05ea01 | |||
| e8e188a30f | |||
| 2a22410550 | |||
| 65cd7095f3 | |||
| 6bb7162263 | |||
| 0a48323043 | |||
| b347a926c2 | |||
| d2a179f58b | |||
| 3330cdc69b | |||
| dd1e2b2100 | |||
| 2566bdcedf | |||
| 1ff3fe194e | |||
| 6e2476df02 | |||
| e3fe33245e |
8
.gitignore
vendored
8
.gitignore
vendored
@ -31,11 +31,3 @@ vendor-cache
|
||||
cmd/Desktop-Bridge/deploy
|
||||
cmd/Import-Export/deploy
|
||||
proton-bridge
|
||||
cmd/Desktop-Bridge/*.exe
|
||||
cmd/launcher/*.exe
|
||||
|
||||
# Jetbrains (CLion, Golang) cmake build dirs
|
||||
cmake-build-*/
|
||||
|
||||
# Doxygen doc files
|
||||
_doc/
|
||||
|
||||
@ -16,19 +16,20 @@
|
||||
# along with ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
---
|
||||
image: gitlab.protontech.ch:4567/go/bridge-internal:go18
|
||||
image: gitlab.protontech.ch:4567/go/bridge-internal:latest
|
||||
|
||||
before_script:
|
||||
- eval $(ssh-agent -s)
|
||||
- echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add - > /dev/null
|
||||
|
||||
- mkdir -p .cache/bin
|
||||
- export PATH=$(pwd)/.cache/bin:$PATH
|
||||
- export GOPATH="$CI_PROJECT_DIR/.cache"
|
||||
|
||||
- make install-dev-dependencies
|
||||
- git checkout .
|
||||
|
||||
cache:
|
||||
key: go18-mod
|
||||
key: go-mod
|
||||
paths:
|
||||
- .cache
|
||||
policy: pull
|
||||
@ -51,7 +52,7 @@ cache-push:
|
||||
script:
|
||||
- echo ""
|
||||
cache:
|
||||
key: go18-mod
|
||||
key: go-mod
|
||||
paths:
|
||||
- .cache
|
||||
|
||||
@ -90,6 +91,8 @@ test-linux:
|
||||
test-windows:
|
||||
extends: .build-windows-base
|
||||
stage: test
|
||||
only:
|
||||
- branches
|
||||
script:
|
||||
- make test
|
||||
|
||||
@ -109,14 +112,26 @@ dependency-updates:
|
||||
|
||||
# Stage: BUILD
|
||||
|
||||
build-qml:
|
||||
tags:
|
||||
- small
|
||||
only:
|
||||
- branches
|
||||
stage: build
|
||||
artifacts:
|
||||
name: "bridge-qml-$CI_COMMIT_SHORT_SHA"
|
||||
expire_in: 1 day
|
||||
paths:
|
||||
- bridge_qml.tgz
|
||||
script:
|
||||
- cd internal/frontend/qml
|
||||
- tar -cvzf ../../../bridge_qml.tgz ./*
|
||||
|
||||
|
||||
.build-base:
|
||||
stage: build
|
||||
rules:
|
||||
- if: $CI_JOB_NAME =~ /test/ && $CI_PIPELINE_SOURCE == "merge_request_event"
|
||||
when: always
|
||||
- if: $CI_JOB_NAME =~ /qa/ && $CI_PIPELINE_SOURCE == "merge_request_event"
|
||||
when: always
|
||||
- when: manual
|
||||
only:
|
||||
- manual
|
||||
before_script:
|
||||
- mkdir -p .cache/bin
|
||||
- export PATH=$(pwd)/.cache/bin:$PATH
|
||||
@ -137,12 +152,14 @@ dependency-updates:
|
||||
|
||||
build-linux:
|
||||
extends: .build-base
|
||||
image: gitlab.protontech.ch:4567/go/bridge-internal:qt6
|
||||
artifacts:
|
||||
name: "bridge-linux-$CI_COMMIT_SHORT_SHA"
|
||||
|
||||
build-linux-qa:
|
||||
extends: build-linux
|
||||
only:
|
||||
- web
|
||||
- branches
|
||||
variables:
|
||||
BUILD_TAGS: "build_qa"
|
||||
artifacts:
|
||||
@ -175,6 +192,9 @@ build-darwin:
|
||||
|
||||
build-darwin-qa:
|
||||
extends: .build-darwin-base
|
||||
only:
|
||||
- web
|
||||
- branches
|
||||
variables:
|
||||
BUILD_TAGS: "build_qa"
|
||||
artifacts:
|
||||
@ -184,16 +204,14 @@ build-darwin-qa:
|
||||
.build-windows-base:
|
||||
extends: .build-base
|
||||
before_script:
|
||||
- export GOROOT=/c/Go1.18/
|
||||
- export GOROOT=/c/Go
|
||||
- export PATH=$GOROOT/bin:$PATH
|
||||
- export GOARCH=amd64
|
||||
- export GOPATH=~/go18
|
||||
- export GOPATH=~/go
|
||||
- export GO111MODULE=on
|
||||
- export PATH="${GOPATH}/bin:${PATH}"
|
||||
- export PATH=$GOPATH/bin:$PATH
|
||||
- export MSYSTEM=
|
||||
- export QT6DIR=/c/grrrQt/6.3.1/msvc2019_64
|
||||
- export PATH=$PATH:${QT6DIR}/bin
|
||||
- export PATH="/c/Program Files/Microsoft Visual Studio/2022/Community/Common7/IDE/CommonExtensions/Microsoft/CMake/CMake/bin:$PATH"
|
||||
- export PATH=$PATH:/c/grrrQt/5.13.2/mingw73_64/bin
|
||||
script:
|
||||
- make build
|
||||
- git diff && git diff-index --quiet HEAD
|
||||
@ -207,6 +225,9 @@ build-windows:
|
||||
|
||||
build-windows-qa:
|
||||
extends: .build-windows-base
|
||||
only:
|
||||
- web
|
||||
- branches
|
||||
variables:
|
||||
BUILD_TAGS: "build_qa"
|
||||
artifacts:
|
||||
@ -228,7 +249,7 @@ check-gobinsec:
|
||||
script:
|
||||
- "[ ! -f ./gobinsec-cache.yml ] && wget bridgeteam.protontech.ch/bridgeteam/gobinsec-cache.yml"
|
||||
- cat ./gobinsec-cache.yml
|
||||
- gobinsec -wait -cache -config utils/gobinsec_conf.yml build/proton-bridge
|
||||
- gobinsec -cache -config utils/gobinsec_conf.yml build/proton-bridge
|
||||
|
||||
|
||||
|
||||
|
||||
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -1,3 +0,0 @@
|
||||
[submodule "submodules/vcpkg"]
|
||||
path = extern/vcpkg
|
||||
url = https://github.com/Microsoft/vcpkg.git
|
||||
@ -3,7 +3,6 @@ run:
|
||||
timeout: 10m
|
||||
skip-dirs:
|
||||
- pkg/mime
|
||||
- extern
|
||||
|
||||
issues:
|
||||
exclude-use-default: false
|
||||
|
||||
@ -21,8 +21,11 @@ Proton Mail Bridge includes the following 3rd party software:
|
||||
* [Qt](https://www.qt.io/) | Available under [multiple licences](https://www.qt.io/licensing)
|
||||
|
||||
<!-- START AUTOGEN -->
|
||||
* [docker-credential-helpers](https://github.com/docker/docker-credential-helpers) available under [license](https://github.com/docker/docker-credential-helpers/blob/master/LICENSE)
|
||||
* [go-imap](https://github.com/emersion/go-imap) available under [license](https://github.com/emersion/go-imap/blob/master/LICENSE)
|
||||
* [notificator](https://github.com/0xAX/notificator) available under [license](https://github.com/0xAX/notificator/blob/master/LICENSE)
|
||||
* [semver](https://github.com/Masterminds/semver/v3) available under [license](https://github.com/Masterminds/semver/v3/blob/master/LICENSE)
|
||||
* [bcrypt](https://github.com/ProtonMail/bcrypt) available under [license](https://github.com/ProtonMail/bcrypt/blob/master/LICENSE)
|
||||
* [go-autostart](https://github.com/ProtonMail/go-autostart) available under [license](https://github.com/ProtonMail/go-autostart/blob/master/LICENSE)
|
||||
* [go-crypto](https://github.com/ProtonMail/go-crypto) available under [license](https://github.com/ProtonMail/go-crypto/blob/master/LICENSE)
|
||||
* [go-imap-id](https://github.com/ProtonMail/go-imap-id) available under [license](https://github.com/ProtonMail/go-imap-id/blob/master/LICENSE)
|
||||
@ -32,13 +35,14 @@ Proton Mail Bridge includes the following 3rd party software:
|
||||
* [gopenpgp](https://github.com/ProtonMail/gopenpgp/v2) available under [license](https://github.com/ProtonMail/gopenpgp/v2/blob/master/LICENSE)
|
||||
* [goquery](https://github.com/PuerkitoBio/goquery) available under [license](https://github.com/PuerkitoBio/goquery/blob/master/LICENSE)
|
||||
* [ishell](https://github.com/abiosoft/ishell) available under [license](https://github.com/abiosoft/ishell/blob/master/LICENSE)
|
||||
* [readline](https://github.com/abiosoft/readline) available under [license](https://github.com/abiosoft/readline/blob/master/LICENSE)
|
||||
* [go-singleinstance](https://github.com/allan-simon/go-singleinstance) available under [license](https://github.com/allan-simon/go-singleinstance/blob/master/LICENSE)
|
||||
* [juniper](https://github.com/bradenaw/juniper) available under [license](https://github.com/bradenaw/juniper/blob/master/LICENSE)
|
||||
* [logex](https://github.com/chzyer/logex) available under [license](https://github.com/chzyer/logex/blob/master/LICENSE)
|
||||
* [test](https://github.com/chzyer/test) available under [license](https://github.com/chzyer/test/blob/master/LICENSE)
|
||||
* [godog](https://github.com/cucumber/godog) available under [license](https://github.com/cucumber/godog/blob/master/LICENSE)
|
||||
* [messages-go](https://github.com/cucumber/messages-go/v16) available under [license](https://github.com/cucumber/messages-go/v16/blob/master/LICENSE)
|
||||
* [docker-credential-helpers](https://github.com/docker/docker-credential-helpers) available under [license](https://github.com/docker/docker-credential-helpers/blob/master/LICENSE)
|
||||
* [go-sysinfo](https://github.com/elastic/go-sysinfo) available under [license](https://github.com/elastic/go-sysinfo/blob/master/LICENSE)
|
||||
* [go-imap](https://github.com/emersion/go-imap) available under [license](https://github.com/emersion/go-imap/blob/master/LICENSE)
|
||||
* [go-windows](https://github.com/elastic/go-windows) available under [license](https://github.com/elastic/go-windows/blob/master/LICENSE)
|
||||
* [go-imap-appendlimit](https://github.com/emersion/go-imap-appendlimit) available under [license](https://github.com/emersion/go-imap-appendlimit/blob/master/LICENSE)
|
||||
* [go-imap-move](https://github.com/emersion/go-imap-move) available under [license](https://github.com/emersion/go-imap-move/blob/master/LICENSE)
|
||||
* [go-imap-quota](https://github.com/emersion/go-imap-quota) available under [license](https://github.com/emersion/go-imap-quota/blob/master/LICENSE)
|
||||
@ -47,7 +51,9 @@ Proton Mail Bridge includes the following 3rd party software:
|
||||
* [go-sasl](https://github.com/emersion/go-sasl) available under [license](https://github.com/emersion/go-sasl/blob/master/LICENSE)
|
||||
* [go-smtp](https://github.com/emersion/go-smtp) available under [license](https://github.com/emersion/go-smtp/blob/master/LICENSE)
|
||||
* [go-textwrapper](https://github.com/emersion/go-textwrapper) available under [license](https://github.com/emersion/go-textwrapper/blob/master/LICENSE)
|
||||
* [go-vcard](https://github.com/emersion/go-vcard) available under [license](https://github.com/emersion/go-vcard/blob/master/LICENSE)
|
||||
* [color](https://github.com/fatih/color) available under [license](https://github.com/fatih/color/blob/master/LICENSE)
|
||||
* [go-shlex](https://github.com/flynn-archive/go-shlex) available under [license](https://github.com/flynn-archive/go-shlex/blob/master/LICENSE)
|
||||
* [sentry-go](https://github.com/getsentry/sentry-go) available under [license](https://github.com/getsentry/sentry-go/blob/master/LICENSE)
|
||||
* [resty](https://github.com/go-resty/resty/v2) available under [license](https://github.com/go-resty/resty/v2/blob/master/LICENSE)
|
||||
* [dbus](https://github.com/godbus/dbus) available under [license](https://github.com/godbus/dbus/blob/master/LICENSE)
|
||||
@ -55,63 +61,31 @@ Proton Mail Bridge includes the following 3rd party software:
|
||||
* [go-cmp](https://github.com/google/go-cmp) available under [license](https://github.com/google/go-cmp/blob/master/LICENSE)
|
||||
* [uuid](https://github.com/google/uuid) available under [license](https://github.com/google/uuid/blob/master/LICENSE)
|
||||
* [go-multierror](https://github.com/hashicorp/go-multierror) available under [license](https://github.com/hashicorp/go-multierror/blob/master/LICENSE)
|
||||
* [bcrypt](https://github.com/jameskeane/bcrypt) available under [license](https://github.com/jameskeane/bcrypt/blob/master/LICENSE)
|
||||
* [html2text](https://github.com/jaytaylor/html2text) available under [license](https://github.com/jaytaylor/html2text/blob/master/LICENSE)
|
||||
* [go-keychain](https://github.com/keybase/go-keychain) available under [license](https://github.com/keybase/go-keychain/blob/master/LICENSE)
|
||||
* [text](https://github.com/kr/text) available under [license](https://github.com/kr/text/blob/master/LICENSE)
|
||||
* [aurora](https://github.com/logrusorgru/aurora) available under [license](https://github.com/logrusorgru/aurora/blob/master/LICENSE)
|
||||
* [go-runewidth](https://github.com/mattn/go-runewidth) available under [license](https://github.com/mattn/go-runewidth/blob/master/LICENSE)
|
||||
* [dns](https://github.com/miekg/dns) available under [license](https://github.com/miekg/dns/blob/master/LICENSE)
|
||||
* [pretty](https://github.com/niemeyer/pretty) available under [license](https://github.com/niemeyer/pretty/blob/master/LICENSE)
|
||||
* [jsondiff](https://github.com/nsf/jsondiff) available under [license](https://github.com/nsf/jsondiff/blob/master/LICENSE)
|
||||
* [tablewriter](https://github.com/olekukonko/tablewriter) available under [license](https://github.com/olekukonko/tablewriter/blob/master/LICENSE)
|
||||
* [errors](https://github.com/pkg/errors) available under [license](https://github.com/pkg/errors/blob/master/LICENSE)
|
||||
* [procfs](https://github.com/prometheus/procfs) available under [license](https://github.com/prometheus/procfs/blob/master/LICENSE)
|
||||
* [du](https://github.com/ricochet2200/go-disk-usage/du) available under [license](https://github.com/ricochet2200/go-disk-usage/du/blob/master/LICENSE)
|
||||
* [logrus](https://github.com/sirupsen/logrus) available under [license](https://github.com/sirupsen/logrus/blob/master/LICENSE)
|
||||
* [bom](https://github.com/ssor/bom) available under [license](https://github.com/ssor/bom/blob/master/LICENSE)
|
||||
* [testify](https://github.com/stretchr/testify) available under [license](https://github.com/stretchr/testify/blob/master/LICENSE)
|
||||
* [qt](https://github.com/therecipe/qt) available under [license](https://github.com/therecipe/qt/blob/master/LICENSE)
|
||||
* [cli](https://github.com/urfave/cli/v2) available under [license](https://github.com/urfave/cli/v2/blob/master/LICENSE)
|
||||
* [msgpack](https://github.com/vmihailenco/msgpack/v5) available under [license](https://github.com/vmihailenco/msgpack/v5/blob/master/LICENSE)
|
||||
* [bbolt](https://go.etcd.io/bbolt) available under [license](https://github.com/etcd-io/bbolt/blob/master/LICENSE)
|
||||
* [exp](https://golang.org/x/exp) available under [license](https://cs.opensource.google/go/x/exp/+/master:LICENSE)
|
||||
* [crypto](https://golang.org/x/crypto) available under [license](https://cs.opensource.google/go/x/crypto/+/master:LICENSE)
|
||||
* [net](https://golang.org/x/net) available under [license](https://cs.opensource.google/go/x/net/+/master:LICENSE)
|
||||
* [sys](https://golang.org/x/sys) available under [license](https://cs.opensource.google/go/x/sys/+/master:LICENSE)
|
||||
* [text](https://golang.org/x/text) available under [license](https://cs.opensource.google/go/x/text/+/master:LICENSE)
|
||||
* [grpc](https://google.golang.org/grpc) available under [license](https://github.com/grpc/grpc-go/blob/master/LICENSE)
|
||||
* [protobuf](https://google.golang.org/protobuf) available under [license](https://github.com/protocolbuffers/protobuf/blob/main/LICENSE)
|
||||
* [plist](https://howett.net/plist) available under [license](https://github.com/DHowett/go-plist/blob/main/LICENSE)
|
||||
* [bcrypt](https://github.com/ProtonMail/bcrypt) available under [license](https://github.com/ProtonMail/bcrypt/blob/master/LICENSE)
|
||||
* [go-mime](https://github.com/ProtonMail/go-mime) available under [license](https://github.com/ProtonMail/go-mime/blob/master/LICENSE)
|
||||
* [readline](https://github.com/abiosoft/readline) available under [license](https://github.com/abiosoft/readline/blob/master/LICENSE)
|
||||
* [cascadia](https://github.com/andybalholm/cascadia) available under [license](https://github.com/andybalholm/cascadia/blob/master/LICENSE)
|
||||
* [antlr](https://github.com/antlr/antlr4/runtime/Go/antlr) available under [license](https://github.com/antlr/antlr4/runtime/Go/antlr/blob/master/LICENSE)
|
||||
* [test](https://github.com/chzyer/test) available under [license](https://github.com/chzyer/test/blob/master/LICENSE)
|
||||
* [circl](https://github.com/cloudflare/circl) available under [license](https://github.com/cloudflare/circl/blob/master/LICENSE)
|
||||
* [go-md2man](https://github.com/cpuguy83/go-md2man/v2) available under [license](https://github.com/cpuguy83/go-md2man/v2/blob/master/LICENSE)
|
||||
* [saferith](https://github.com/cronokirby/saferith) available under [license](https://github.com/cronokirby/saferith/blob/master/LICENSE)
|
||||
* [gherkin-go](https://github.com/cucumber/gherkin-go/v19) available under [license](https://github.com/cucumber/gherkin-go/v19/blob/master/LICENSE)
|
||||
* [wincred](https://github.com/danieljoos/wincred) available under [license](https://github.com/danieljoos/wincred/blob/master/LICENSE)
|
||||
* [go-spew](https://github.com/davecgh/go-spew) available under [license](https://github.com/davecgh/go-spew/blob/master/LICENSE)
|
||||
* [go-windows](https://github.com/elastic/go-windows) available under [license](https://github.com/elastic/go-windows/blob/master/LICENSE)
|
||||
* [go-vcard](https://github.com/emersion/go-vcard) available under [license](https://github.com/emersion/go-vcard/blob/master/LICENSE)
|
||||
* [go-shlex](https://github.com/flynn-archive/go-shlex) available under [license](https://github.com/flynn-archive/go-shlex/blob/master/LICENSE)
|
||||
* [uuid](https://github.com/gofrs/uuid) available under [license](https://github.com/gofrs/uuid/blob/master/LICENSE)
|
||||
* [protobuf](https://github.com/golang/protobuf) available under [license](https://github.com/golang/protobuf/blob/master/LICENSE)
|
||||
* [errwrap](https://github.com/hashicorp/errwrap) available under [license](https://github.com/hashicorp/errwrap/blob/master/LICENSE)
|
||||
* [go-immutable-radix](https://github.com/hashicorp/go-immutable-radix) available under [license](https://github.com/hashicorp/go-immutable-radix/blob/master/LICENSE)
|
||||
* [go-memdb](https://github.com/hashicorp/go-memdb) available under [license](https://github.com/hashicorp/go-memdb/blob/master/LICENSE)
|
||||
* [golang-lru](https://github.com/hashicorp/golang-lru) available under [license](https://github.com/hashicorp/golang-lru/blob/master/LICENSE)
|
||||
* [multierror](https://github.com/joeshaw/multierror) available under [license](https://github.com/joeshaw/multierror/blob/master/LICENSE)
|
||||
* [go-colorable](https://github.com/mattn/go-colorable) available under [license](https://github.com/mattn/go-colorable/blob/master/LICENSE)
|
||||
* [go-isatty](https://github.com/mattn/go-isatty) available under [license](https://github.com/mattn/go-isatty/blob/master/LICENSE)
|
||||
* [go-runewidth](https://github.com/mattn/go-runewidth) available under [license](https://github.com/mattn/go-runewidth/blob/master/LICENSE)
|
||||
* [tablewriter](https://github.com/olekukonko/tablewriter) available under [license](https://github.com/olekukonko/tablewriter/blob/master/LICENSE)
|
||||
* [go-difflib](https://github.com/pmezard/go-difflib) available under [license](https://github.com/pmezard/go-difflib/blob/master/LICENSE)
|
||||
* [procfs](https://github.com/prometheus/procfs) available under [license](https://github.com/prometheus/procfs/blob/master/LICENSE)
|
||||
* [blackfriday](https://github.com/russross/blackfriday/v2) available under [license](https://github.com/russross/blackfriday/v2/blob/master/LICENSE)
|
||||
* [pflag](https://github.com/spf13/pflag) available under [license](https://github.com/spf13/pflag/blob/master/LICENSE)
|
||||
* [bom](https://github.com/ssor/bom) available under [license](https://github.com/ssor/bom/blob/master/LICENSE)
|
||||
* [tagparser](https://github.com/vmihailenco/tagparser/v2) available under [license](https://github.com/vmihailenco/tagparser/v2/blob/master/LICENSE)
|
||||
* [smetrics](https://github.com/xrash/smetrics) available under [license](https://github.com/xrash/smetrics/blob/master/LICENSE)
|
||||
* [crypto](https://golang.org/x/crypto) available under [license](https://cs.opensource.google/go/x/crypto/+/master:LICENSE)
|
||||
* [mod](https://golang.org/x/mod) available under [license](https://cs.opensource.google/go/x/mod/+/master:LICENSE)
|
||||
* [tools](https://golang.org/x/tools) available under [license](https://cs.opensource.google/go/x/tools/+/master:LICENSE)
|
||||
* [genproto](https://google.golang.org/genproto)
|
||||
gopkg.in/yaml.v3
|
||||
* [docker-credential-helpers](https://github.com/ProtonMail/docker-credential-helpers) available under [license](https://github.com/ProtonMail/docker-credential-helpers/blob/master/LICENSE)
|
||||
* [go-imap](https://github.com/ProtonMail/go-imap) available under [license](https://github.com/ProtonMail/go-imap/blob/master/LICENSE)
|
||||
* [go-message](https://github.com/ProtonMail/go-message) available under [license](https://github.com/ProtonMail/go-message/blob/master/LICENSE)
|
||||
|
||||
32
Changelog.md
32
Changelog.md
@ -2,38 +2,6 @@
|
||||
|
||||
Changelog [format](http://keepachangelog.com/en/1.0.0/)
|
||||
|
||||
## [Bridge 2.4.0] Osney
|
||||
|
||||
### Added
|
||||
* GODT-1551: Upgrade to Qt 6:
|
||||
* Change the app architecture.
|
||||
* Drop therecipe/qt dependency.
|
||||
* Update to go1.18.
|
||||
* Update to Qt 6.3.2.
|
||||
* GODT-1170 GODT-1675: Native Mac M1 release.
|
||||
|
||||
|
||||
## [Bridge 2.3.0] Nihonbashi
|
||||
|
||||
### Added
|
||||
* GODT-1739: Opt-out All Mail visibility in settings file.
|
||||
* GODT-1794: CLI wording.
|
||||
* GODT-1794: Add confirmation dialog and change wording.
|
||||
* GODT-1741: GUI and CLI settings to change visibility of All Mail folder.
|
||||
* GODT-1740: Opt-out All Mail visibility in settings file.
|
||||
|
||||
### Changed
|
||||
* GODT-1737: Improve logging during import.
|
||||
* GODT-1754: Add logs for unilateral updates and SEARCH.
|
||||
|
||||
### Fixed
|
||||
* GODT-1840: Use Safe map for mailboxID cache.
|
||||
* GODT-1795: Fix automatic installation of profile for AppleMail on macOS Ventura beta (qt 5).
|
||||
* GODT-1833: Fix gobinsec cache.
|
||||
* GODT-1799: Fix dependency link.
|
||||
* Other: Update SSL certificate fingerprint for test.
|
||||
|
||||
|
||||
## [Bridge 2.2.2] Millau
|
||||
|
||||
### Added
|
||||
|
||||
227
Makefile
227
Makefile
@ -5,28 +5,25 @@ export GO111MODULE=on
|
||||
GOOS:=$(shell go env GOOS)
|
||||
TARGET_CMD?=Desktop-Bridge
|
||||
TARGET_OS?=${GOOS}
|
||||
ROOT_DIR:=$(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
|
||||
|
||||
## Build
|
||||
.PHONY: build build-gui build-nogui build-launcher versioner hasher
|
||||
.PHONY: build build-nogui build-launcher versioner hasher
|
||||
|
||||
# Keep version hardcoded so app build works also without Git repository.
|
||||
BRIDGE_APP_VERSION?=2.4.0+git
|
||||
BRIDGE_APP_VERSION?=2.2.2+git
|
||||
APP_VERSION:=${BRIDGE_APP_VERSION}
|
||||
APP_FULL_NAME:=Proton Mail Bridge
|
||||
APP_VENDOR:=Proton AG
|
||||
SRC_ICO:=bridge.ico
|
||||
SRC_ICNS:=Bridge.icns
|
||||
SRC_SVG:=bridge.svg
|
||||
EXE_NAME:=proton-bridge
|
||||
CONFIGNAME:=bridge
|
||||
REVISION:=$(shell git rev-parse --short=10 HEAD)
|
||||
BUILD_TIME:=$(shell date +%FT%T%z)
|
||||
|
||||
BUILD_FLAGS:=-tags='${BUILD_TAGS}'
|
||||
BUILD_FLAGS_LAUNCHER:=${BUILD_FLAGS}
|
||||
BUILD_FLAGS_GUI:=-tags='${BUILD_TAGS} build_qt'
|
||||
GO_LDFLAGS:=$(addprefix -X github.com/ProtonMail/proton-bridge/v2/internal/constants., Version=${APP_VERSION} Revision=${REVISION} BuildTime=${BUILD_TIME})
|
||||
GO_LDFLAGS+=-X "github.com/ProtonMail/proton-bridge/v2/internal/constants.FullAppName=${APP_FULL_NAME}"
|
||||
GO_LDFLAGS:=$(addprefix -X github.com/ProtonMail/proton-bridge/v2/internal/constants.,Version=${APP_VERSION} Revision=${REVISION} BuildTime=${BUILD_TIME})
|
||||
ifneq "${BUILD_LDFLAGS}" ""
|
||||
GO_LDFLAGS+=${BUILD_LDFLAGS}
|
||||
endif
|
||||
@ -36,34 +33,27 @@ ifeq "${TARGET_OS}" "windows"
|
||||
endif
|
||||
|
||||
BUILD_FLAGS+=-ldflags '${GO_LDFLAGS}'
|
||||
BUILD_FLAGS_GUI+=-ldflags "${GO_LDFLAGS}"
|
||||
BUILD_FLAGS_GUI+=-ldflags '${GO_LDFLAGS}'
|
||||
BUILD_FLAGS_LAUNCHER+=-ldflags '${GO_LDFLAGS_LAUNCHER}'
|
||||
|
||||
DEPLOY_DIR:=cmd/${TARGET_CMD}/deploy
|
||||
ICO_FILES:=
|
||||
DIRNAME:=$(shell basename ${CURDIR})
|
||||
|
||||
LAUNCHER_EXE:=proton-bridge
|
||||
BRIDGE_EXE=bridge
|
||||
BRIDGE_GUI_EXE_NAME=bridge-gui
|
||||
BRIDGE_GUI_EXE=${BRIDGE_GUI_EXE_NAME}
|
||||
LAUNCHER_PATH:=./cmd/launcher/
|
||||
|
||||
EXE:=${EXE_NAME}
|
||||
EXE_QT:=${DIRNAME}
|
||||
ifeq "${TARGET_OS}" "windows"
|
||||
BRIDGE_EXE:=${BRIDGE_EXE}.exe
|
||||
BRIDGE_GUI_EXE:=${BRIDGE_GUI_EXE}.exe
|
||||
LAUNCHER_EXE:=${LAUNCHER_EXE}.exe
|
||||
EXE:=${EXE}.exe
|
||||
EXE_QT:=${EXE_QT}.exe
|
||||
RESOURCE_FILE:=resource.syso
|
||||
endif
|
||||
ifeq "${TARGET_OS}" "darwin"
|
||||
BRIDGE_EXE_NAME:=${BRIDGE_EXE}
|
||||
BRIDGE_EXE:=${BRIDGE_EXE}.app
|
||||
BRIDGE_GUI_EXE:=${BRIDGE_GUI_EXE}.app
|
||||
EXE_BINARY_DARWIN:=Contents/MacOS/${BRIDGE_GUI_EXE_NAME}
|
||||
EXE_TARGET_DARWIN:=${DEPLOY_DIR}/${TARGET_OS}/${LAUNCHER_EXE}.app
|
||||
DARWINAPP_CONTENTS:=${EXE_TARGET_DARWIN}/Contents
|
||||
DARWINAPP_CONTENTS:=${DEPLOY_DIR}/darwin/${EXE}.app/Contents
|
||||
EXE:=${EXE}.app
|
||||
EXE_QT:=${EXE_QT}.app
|
||||
EXE_BINARY_DARWIN:=/Contents/MacOS/${EXE_NAME}
|
||||
endif
|
||||
EXE_TARGET:=${DEPLOY_DIR}/${TARGET_OS}/${BRIDGE_EXE}
|
||||
EXE_GUI_TARGET:=${DEPLOY_DIR}/${TARGET_OS}/${BRIDGE_GUI_EXE}
|
||||
EXE_TARGET:=${DEPLOY_DIR}/${TARGET_OS}/${EXE}
|
||||
EXE_QT_TARGET:=${DEPLOY_DIR}/${TARGET_OS}/${EXE_QT}
|
||||
|
||||
TGZ_TARGET:=bridge_${TARGET_OS}_${REVISION}.tgz
|
||||
|
||||
@ -73,32 +63,19 @@ else
|
||||
VENDOR_TARGET=update-vendor
|
||||
endif
|
||||
|
||||
build: build-gui
|
||||
build: ${TGZ_TARGET}
|
||||
|
||||
build-gui: ${TGZ_TARGET}
|
||||
build-nogui: gofiles
|
||||
go build ${BUILD_FLAGS} -o ${EXE_NAME} cmd/${TARGET_CMD}/main.go
|
||||
|
||||
build-nogui: ${EXE_NAME}
|
||||
|
||||
go-build=go build $(1) -o $(2) $(3)
|
||||
go-build-unify=${go-build}
|
||||
ifeq "${GOOS}-$(shell uname -m)" "darwin-arm64"
|
||||
go-build-unify= \
|
||||
CGO_ENABLED=1 GOARCH=arm64 $(call go-build,$(1),$(2)_arm,$(3)) && \
|
||||
CGO_ENABLED=1 GOARCH=amd64 $(call go-build,$(1),$(2)_amd,$(3)) && \
|
||||
lipo -create -output $(2) $(2)_arm $(2)_amd && rm -f $(2)_arm $(2)_amd
|
||||
ifeq "${GOOS}" "windows"
|
||||
PRERESOURCECMD:=cp ./resource.syso ./cmd/launcher/resource.syso
|
||||
POSTRESOURCECMD:=rm -f ./cmd/launcher/resource.syso
|
||||
endif
|
||||
|
||||
${EXE_NAME}: gofiles
|
||||
$(call go-build-unify,${BUILD_FLAGS},"${EXE_NAME}","cmd/${TARGET_CMD}/main.go")
|
||||
|
||||
build-launcher: ${RESOURCE_FILE}
|
||||
ifeq "${GOOS}" "windows"
|
||||
powershell Copy-Item ${ROOT_DIR}/${RESOURCE_FILE} ${ROOT_DIR}/${LAUNCHER_PATH}${RESOURCE_FILE}
|
||||
endif
|
||||
$(call go-build-unify,${BUILD_FLAGS_LAUNCHER},"${LAUNCHER_EXE}","${LAUNCHER_PATH}")
|
||||
ifeq "${GOOS}" "windows"
|
||||
powershell Remove-Item ${ROOT_DIR}/${LAUNCHER_PATH}${RESOURCE_FILE} -Force
|
||||
endif
|
||||
${PRERESOURCECMD}
|
||||
go build ${BUILD_FLAGS_LAUNCHER} -o launcher-${EXE} ./cmd/launcher/
|
||||
${POSTRESOURCECMD}
|
||||
|
||||
versioner:
|
||||
go build ${BUILD_FLAGS} -o versioner utils/versioner/main.go
|
||||
@ -108,66 +85,85 @@ hasher:
|
||||
|
||||
${TGZ_TARGET}: ${DEPLOY_DIR}/${TARGET_OS}
|
||||
rm -f $@
|
||||
tar -czvf $@ -C ${DEPLOY_DIR}/${TARGET_OS} .
|
||||
cd ${DEPLOY_DIR}/${TARGET_OS} && tar -czvf ../../../../$@ .
|
||||
|
||||
${DEPLOY_DIR}/linux: ${EXE_TARGET} build-launcher
|
||||
${DEPLOY_DIR}/linux: ${EXE_TARGET}
|
||||
cp -pf ./dist/${SRC_SVG} ${DEPLOY_DIR}/linux/logo.svg
|
||||
cp -pf ./LICENSE ${DEPLOY_DIR}/linux/
|
||||
cp -pf ./Changelog.md ${DEPLOY_DIR}/linux/
|
||||
cp -pf ./dist/${EXE_NAME}.desktop ${DEPLOY_DIR}/linux/
|
||||
cp -pf ${LAUNCHER_EXE} ${DEPLOY_DIR}/linux/
|
||||
|
||||
${DEPLOY_DIR}/darwin: ${EXE_TARGET} build-launcher
|
||||
mv ${EXE_GUI_TARGET} ${EXE_TARGET_DARWIN}
|
||||
mv ${EXE_TARGET} ${DARWINAPP_CONTENTS}/MacOS/${BRIDGE_EXE_NAME}
|
||||
perl -i -pe"s/>${BRIDGE_GUI_EXE_NAME}/>${LAUNCHER_EXE}/g" ${DARWINAPP_CONTENTS}/Info.plist
|
||||
${DEPLOY_DIR}/darwin: ${EXE_TARGET}
|
||||
if [ "${DIRNAME}" != "${EXE_NAME}" ]; then \
|
||||
mv ${EXE_TARGET}/Contents/MacOS/{${DIRNAME},${EXE_NAME}}; \
|
||||
perl -i -pe"s/>${DIRNAME}/>${EXE_NAME}/g" ${EXE_TARGET}/Contents/Info.plist; \
|
||||
fi
|
||||
cp ./dist/${SRC_ICNS} ${DARWINAPP_CONTENTS}/Resources/${SRC_ICNS}
|
||||
cp LICENSE ${DARWINAPP_CONTENTS}/Resources/
|
||||
rm -rf "${DARWINAPP_CONTENTS}/Frameworks/QtWebEngine.framework"
|
||||
rm -rf "${DARWINAPP_CONTENTS}/Frameworks/QtWebView.framework"
|
||||
rm -rf "${DARWINAPP_CONTENTS}/Frameworks/QtWebEngineCore.framework"
|
||||
cp ${LAUNCHER_EXE} ${DARWINAPP_CONTENTS}/MacOS/${LAUNCHER_EXE}
|
||||
./utils/remove_non_relative_links_darwin.sh "${EXE_TARGET_DARWIN}/${EXE_BINARY_DARWIN}"
|
||||
./utils/remove_non_relative_links_darwin.sh "${EXE_TARGET}${EXE_BINARY_DARWIN}"
|
||||
|
||||
${DEPLOY_DIR}/windows: ${EXE_TARGET} build-launcher
|
||||
${DEPLOY_DIR}/windows: ${EXE_TARGET}
|
||||
cp ./dist/${SRC_ICO} ${DEPLOY_DIR}/windows/logo.ico
|
||||
cp LICENSE ${DEPLOY_DIR}/windows/LICENSE.txt
|
||||
cp ${LAUNCHER_EXE} ${DEPLOY_DIR}/windows/$(notdir ${LAUNCHER_EXE})
|
||||
# plugins are installed in a plugins folder while needs to be near the exe
|
||||
mv ${DEPLOY_DIR}/windows/plugins/* ${DEPLOY_DIR}/windows/.
|
||||
rm -rf ${DEPLOY_DIR}/windows/plugins
|
||||
cp LICENSE ${DEPLOY_DIR}/windows/
|
||||
|
||||
QT_BUILD_TARGET:=build desktop
|
||||
ifneq "${GOOS}" "${TARGET_OS}"
|
||||
ifeq "${TARGET_OS}" "windows"
|
||||
QT_BUILD_TARGET:=-docker build windows_64_shared
|
||||
endif
|
||||
endif
|
||||
|
||||
${EXE_TARGET}: check-has-go gofiles ${RESOURCE_FILE} ${VENDOR_TARGET}
|
||||
rm -rf deploy ${TARGET_OS} ${DEPLOY_DIR}
|
||||
cp cmd/${TARGET_CMD}/main.go .
|
||||
qtdeploy ${BUILD_FLAGS_GUI} ${QT_BUILD_TARGET}
|
||||
mv deploy cmd/${TARGET_CMD}
|
||||
if [ "${EXE_QT_TARGET}" != "${EXE_TARGET}" ]; then mv ${EXE_QT_TARGET} ${EXE_TARGET}; fi
|
||||
rm -rf ${TARGET_OS} main.go
|
||||
|
||||
${EXE_TARGET}: check-build-essentials ${EXE_NAME}
|
||||
# TODO: resource.syso for windows
|
||||
cd internal/frontend/bridge-gui/bridge-gui && \
|
||||
BRIDGE_APP_FULL_NAME="${APP_FULL_NAME}" \
|
||||
BRIDGE_VENDOR="${APP_VENDOR}" \
|
||||
BRIDGE_APP_VERSION=${APP_VERSION} \
|
||||
BRIDGE_REVISION=${REVISION} \
|
||||
BRIDGE_BUILD_TIME=${BUILD_TIME} \
|
||||
BRIDGE_GUI_BUILD_CONFIG=Release \
|
||||
BRIDGE_INSTALL_PATH=${ROOT_DIR}/${DEPLOY_DIR}/${GOOS} \
|
||||
./build.sh install
|
||||
mv "${ROOT_DIR}/${EXE_NAME}" "$(ROOT_DIR)/${EXE_TARGET}"
|
||||
|
||||
WINDRES_YEAR:=$(shell date +%Y)
|
||||
APP_VERSION_COMMA:=$(shell echo "${APP_VERSION}" | sed -e 's/[^0-9,.]*//g' -e 's/\./,/g')
|
||||
${RESOURCE_FILE}: ./dist/info.rc ./dist/${SRC_ICO} .FORCE
|
||||
resource.syso: ./dist/info.rc ./dist/${SRC_ICO} .FORCE
|
||||
rm -f ./*.syso
|
||||
windres --target=pe-x86-64 \
|
||||
-I ./internal/frontend/share/ \
|
||||
-D ICO_FILE=${SRC_ICO} \
|
||||
-D EXE_NAME="${EXE_NAME}" \
|
||||
-D FILE_VERSION="${APP_VERSION}" \
|
||||
-D ORIGINAL_FILE_NAME="${EXE}" \
|
||||
-D PRODUCT_VERSION="${APP_VERSION}" \
|
||||
-D FILE_VERSION_COMMA=${APP_VERSION_COMMA} \
|
||||
-D YEAR=${WINDRES_YEAR} \
|
||||
-o ./${RESOURCE_FILE} $<
|
||||
windres --target=pe-x86-64 -I ./internal/frontend/share/ -D ICO_FILE=${SRC_ICO} -D EXE_NAME="${EXE_NAME}" -D FILE_VERSION="${APP_VERSION}" -D ORIGINAL_FILE_NAME="${EXE}" -D PRODUCT_VERSION="${APP_VERSION}" -D FILE_VERSION_COMMA=${APP_VERSION_COMMA} -D YEAR=${WINDRES_YEAR} -o $@ $<
|
||||
|
||||
## Rules for therecipe/qt
|
||||
.PHONY: prepare-vendor update-vendor update-qt-docs
|
||||
THERECIPE_ENV:=github.com/therecipe/env_${TARGET_OS}_amd64_513
|
||||
|
||||
# vendor folder will be deleted by gomod hence we cache the big repo
|
||||
# therecipe/env in order to download it only once
|
||||
vendor-cache/${THERECIPE_ENV}:
|
||||
git clone https://${THERECIPE_ENV}.git vendor-cache/${THERECIPE_ENV}
|
||||
if [ "${TARGET_OS}" == "darwin" ]; then cp -f "./utils/QTBUG-88600/libqcocoa.dylib" "./vendor-cache/${THERECIPE_ENV}/5.13.0/clang_64/plugins/platforms/"; fi;
|
||||
|
||||
# The command used to make symlinks is different on windows.
|
||||
# So if the GOOS is windows and we aren't crossbuilding (in which case the host os would still be *nix)
|
||||
# we need to change the LINKCMD to something windowsy.
|
||||
LINKCMD:=ln -sf ${CURDIR}/vendor-cache/${THERECIPE_ENV} vendor/${THERECIPE_ENV}
|
||||
ifeq "${GOOS}" "windows"
|
||||
WINDIR:=$(subst /c/,c:\\,${CURDIR})/vendor-cache/${THERECIPE_ENV}
|
||||
LINKCMD:=cmd //c 'mklink $(subst /,\,vendor\${THERECIPE_ENV} ${WINDIR})'
|
||||
endif
|
||||
|
||||
prepare-vendor:
|
||||
go install -v -tags=no_env github.com/therecipe/qt/cmd/...
|
||||
go mod vendor
|
||||
|
||||
# update-vendor is PHONY because we need to make sure that we always have updated vendor
|
||||
update-vendor: vendor-cache/${THERECIPE_ENV} prepare-vendor
|
||||
${LINKCMD}
|
||||
|
||||
update-qt-docs:
|
||||
go get github.com/therecipe/qt/internal/binding/files/docs/$(QT_API)
|
||||
|
||||
## Dev dependencies
|
||||
.PHONY: install-devel-tools install-linter install-go-mod-outdated install-git-hooks
|
||||
LINTVER:="v1.47.2"
|
||||
LINTVER:="v1.39.0"
|
||||
LINTSRC:="https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh"
|
||||
|
||||
install-dev-dependencies: install-devel-tools install-linter install-go-mod-outdated
|
||||
@ -181,32 +177,16 @@ install-linter: check-has-go
|
||||
curl -sfL $(LINTSRC) | sh -s -- -b $(shell go env GOPATH)/bin $(LINTVER)
|
||||
|
||||
install-go-mod-outdated:
|
||||
which go-mod-outdated || go install github.com/psampaz/go-mod-outdated@latest
|
||||
which go-mod-outdated || go get -u github.com/psampaz/go-mod-outdated
|
||||
|
||||
install-git-hooks:
|
||||
cp utils/githooks/* .git/hooks/
|
||||
chmod +x .git/hooks/*
|
||||
|
||||
## Checks, mocks and docs
|
||||
.PHONY: check-has-go check-build-essentials add-license change-copyright-year test bench coverage mocks lint-license lint-golang lint updates doc release-notes
|
||||
.PHONY: check-has-go add-license change-copyright-year test bench coverage mocks lint-license lint-golang lint updates doc release-notes
|
||||
check-has-go:
|
||||
@which go || (echo "Install Go-lang!" && exit 1)
|
||||
go version
|
||||
|
||||
|
||||
check_is_installed=if ! which $(1) > /dev/null; then echo "Please install $(1)"; exit 1; fi
|
||||
check-build-essentials: check-qt-dir
|
||||
@$(call check_is_installed,zip)
|
||||
@$(call check_is_installed,unzip)
|
||||
@$(call check_is_installed,tar)
|
||||
@$(call check_is_installed,curl)
|
||||
ifneq "${GOOS}" "windows"
|
||||
@$(call check_is_installed,cmake)
|
||||
@$(call check_is_installed,ninja)
|
||||
endif
|
||||
|
||||
check-qt-dir:
|
||||
@if ! ls "${QT6DIR}/bin/qt.conf" > /dev/null; then echo "Please set QT6DIR"; exit 1; fi
|
||||
|
||||
add-license:
|
||||
./utils/missing_license.sh add
|
||||
@ -215,8 +195,25 @@ change-copyright-year:
|
||||
./utils/missing_license.sh change-year
|
||||
|
||||
test: gofiles
|
||||
@# Listing packages manually to not run Qt folder (which needs to run qtsetup first) and integration tests.
|
||||
go test -coverprofile=/tmp/coverage.out -run=${TESTRUN} \
|
||||
./internal/...\
|
||||
./internal/api/... \
|
||||
./internal/bridge/... \
|
||||
./internal/config/... \
|
||||
./internal/constants/... \
|
||||
./internal/cookies/... \
|
||||
./internal/crash/... \
|
||||
./internal/events/... \
|
||||
./internal/frontend/cli/... \
|
||||
./internal/imap/... \
|
||||
./internal/locations/... \
|
||||
./internal/logging/... \
|
||||
./internal/metrics/... \
|
||||
./internal/smtp/... \
|
||||
./internal/store/... \
|
||||
./internal/updater/... \
|
||||
./internal/users/... \
|
||||
./internal/versioner/... \
|
||||
./pkg/...
|
||||
|
||||
bench:
|
||||
@ -299,7 +296,7 @@ run-debug:
|
||||
run-qml-preview:
|
||||
find internal/frontend/qml/ -iname '*qmlc' | xargs rm -f
|
||||
bridge_preview internal/frontend/qml/Bridge_test.qml
|
||||
|
||||
|
||||
|
||||
clean-frontend-qt:
|
||||
$(MAKE) -C internal/frontend -f Makefile.local clean
|
||||
@ -307,27 +304,15 @@ clean-frontend-qt:
|
||||
clean-vendor: clean-frontend-qt clean-frontend-qt-common
|
||||
rm -rf ./vendor
|
||||
|
||||
clean-gui:
|
||||
cd internal/frontend/bridge-gui/ && \
|
||||
rm -f Version.h && \
|
||||
rm -rf cmake-build-*/
|
||||
|
||||
clean-vcpkg:
|
||||
git submodule deinit -f ./extern/vcpkg
|
||||
rm -rf ./.git/submodule/vcpkg
|
||||
rm -rf ./extern/vcpkg
|
||||
git checkout -- extern/vcpkg
|
||||
|
||||
clean: clean-vendor clean-gui clean-vcpkg
|
||||
clean: clean-vendor
|
||||
rm -rf vendor-cache
|
||||
rm -rf cmd/Desktop-Bridge/deploy
|
||||
rm -rf cmd/Import-Export/deploy
|
||||
rm -f build last.log mem.pprof main.go
|
||||
rm -f ${RESOURCE_FILE}
|
||||
rm -f resource.syso
|
||||
rm -f release-notes/bridge.html
|
||||
rm -f release-notes/import-export.html
|
||||
|
||||
|
||||
.PHONY: generate
|
||||
generate:
|
||||
go generate ./...
|
||||
|
||||
@ -39,11 +39,11 @@ import (
|
||||
|
||||
"github.com/ProtonMail/proton-bridge/v2/internal/app/base"
|
||||
"github.com/ProtonMail/proton-bridge/v2/internal/app/bridge"
|
||||
"github.com/ProtonMail/proton-bridge/v2/internal/constants"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
const (
|
||||
appName = "Proton Mail Bridge"
|
||||
appUsage = "Proton Mail IMAP and SMTP Bridge"
|
||||
configName = "bridge"
|
||||
updateURLName = "bridge"
|
||||
@ -53,7 +53,7 @@ const (
|
||||
|
||||
func main() {
|
||||
base, err := base.New(
|
||||
constants.FullAppName,
|
||||
appName,
|
||||
appUsage,
|
||||
configName,
|
||||
updateURLName,
|
||||
|
||||
@ -22,7 +22,6 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"time"
|
||||
|
||||
"github.com/Masterminds/semver/v3"
|
||||
"github.com/ProtonMail/gopenpgp/v2/crypto"
|
||||
@ -34,9 +33,6 @@ import (
|
||||
"github.com/ProtonMail/proton-bridge/v2/internal/sentry"
|
||||
"github.com/ProtonMail/proton-bridge/v2/internal/updater"
|
||||
"github.com/ProtonMail/proton-bridge/v2/internal/versioner"
|
||||
"github.com/bradenaw/juniper/xslices"
|
||||
"github.com/elastic/go-sysinfo"
|
||||
"github.com/elastic/go-sysinfo/types"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"golang.org/x/sys/execabs"
|
||||
@ -45,13 +41,7 @@ import (
|
||||
const (
|
||||
appName = "Proton Mail Launcher"
|
||||
configName = "bridge"
|
||||
exeName = "bridge"
|
||||
guiName = "bridge-gui"
|
||||
|
||||
FlagCLI = "--cli"
|
||||
FlagCLIShort = "-c"
|
||||
FlagLauncher = "--launcher"
|
||||
FlagWait = "--wait"
|
||||
exeName = "proton-bridge"
|
||||
)
|
||||
|
||||
func main() { //nolint:funlen
|
||||
@ -96,15 +86,9 @@ func main() { //nolint:funlen
|
||||
|
||||
versioner := versioner.New(updatesPath)
|
||||
|
||||
exeToLaunch := guiName
|
||||
args := os.Args[1:]
|
||||
if inCLIMode(args) {
|
||||
exeToLaunch = exeName
|
||||
}
|
||||
|
||||
exe, err := getPathToUpdatedExecutable(exeToLaunch, versioner, kr, reporter)
|
||||
exe, err := getPathToUpdatedExecutable(exeName, versioner, kr, reporter)
|
||||
if err != nil {
|
||||
if exe, err = getFallbackExecutable(exeToLaunch, versioner); err != nil {
|
||||
if exe, err = getFallbackExecutable(exeName, versioner); err != nil {
|
||||
logrus.WithError(err).Fatal("Failed to find any launchable executable")
|
||||
}
|
||||
}
|
||||
@ -114,20 +98,14 @@ func main() { //nolint:funlen
|
||||
logrus.WithError(err).Fatal("Failed to determine path to launcher")
|
||||
}
|
||||
|
||||
args, wait, mainExe := findAndStripWait(args)
|
||||
if wait {
|
||||
waitForProcessToFinish(mainExe)
|
||||
}
|
||||
|
||||
cmd := execabs.Command(exe, appendLauncherPath(launcher, args)...) //nolint:gosec
|
||||
cmd := execabs.Command(exe, appendLauncherPath(launcher, os.Args[1:])...) //nolint:gosec
|
||||
|
||||
cmd.Stdin = os.Stdin
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
|
||||
// On windows, if you use Run(), a terminal stays open; we don't want that.
|
||||
if //goland:noinspection GoBoolExpressions
|
||||
runtime.GOOS == "windows" {
|
||||
if runtime.GOOS == "windows" {
|
||||
err = cmd.Start()
|
||||
} else {
|
||||
err = cmd.Run()
|
||||
@ -138,57 +116,30 @@ func main() { //nolint:funlen
|
||||
}
|
||||
}
|
||||
|
||||
// appendLauncherPath add launcher path if missing.
|
||||
func appendLauncherPath(path string, args []string) []string {
|
||||
if !sliceContains(args, FlagLauncher) {
|
||||
res := append([]string{}, args...)
|
||||
res = append(res, FlagLauncher, path)
|
||||
return res
|
||||
}
|
||||
return args
|
||||
}
|
||||
|
||||
// inCLIMode detect if CLI mode is asked.
|
||||
func inCLIMode(args []string) bool {
|
||||
return sliceContains(args, FlagCLI) || sliceContains(args, FlagCLIShort)
|
||||
}
|
||||
|
||||
// sliceContains checks if a value is present in a list.
|
||||
func sliceContains[T comparable](list []T, s T) bool {
|
||||
return xslices.Any(list, func(arg T) bool { return arg == s })
|
||||
}
|
||||
|
||||
// findAndStrip check if a value is present in s list and remove all occurrences of the value from this list.
|
||||
func findAndStrip[T comparable](slice []T, v T) (strippedList []T, found bool) {
|
||||
strippedList = xslices.Filter(slice, func(value T) bool {
|
||||
return value != v
|
||||
})
|
||||
return strippedList, len(strippedList) != len(slice)
|
||||
}
|
||||
|
||||
// findAndStripWait Check for waiter flag get its value and clean them both.
|
||||
func findAndStripWait(args []string) ([]string, bool, string) {
|
||||
res := append([]string{}, args...)
|
||||
|
||||
hasFlag := false
|
||||
var value string
|
||||
|
||||
for k, v := range res {
|
||||
if v != FlagWait {
|
||||
if v != "--launcher" {
|
||||
continue
|
||||
}
|
||||
|
||||
hasFlag = true
|
||||
|
||||
if k+1 >= len(res) {
|
||||
continue
|
||||
}
|
||||
hasFlag = true
|
||||
value = res[k+1]
|
||||
|
||||
res[k+1] = path
|
||||
}
|
||||
|
||||
if hasFlag {
|
||||
res, _ = findAndStrip(res, FlagWait)
|
||||
res, _ = findAndStrip(res, value)
|
||||
if !hasFlag {
|
||||
res = append(res, "--launcher", path)
|
||||
}
|
||||
return res, hasFlag, value
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
func getPathToUpdatedExecutable(
|
||||
@ -251,44 +202,3 @@ func getFallbackExecutable(name string, versioner *versioner.Versioner) (string,
|
||||
|
||||
return versioner.GetExecutableInDirectory(name, filepath.Dir(launcher))
|
||||
}
|
||||
|
||||
// waitForProcessToFinish waits until the process with the given path is finished.
|
||||
func waitForProcessToFinish(exePath string) {
|
||||
for {
|
||||
processes, err := sysinfo.Processes()
|
||||
if err != nil {
|
||||
logrus.WithError(err).Error("Could not determine running processes")
|
||||
return
|
||||
}
|
||||
|
||||
exeInfo, err := os.Stat(exePath)
|
||||
if err != nil {
|
||||
logrus.WithError(err).WithField("file", exeInfo).Error("Could not retrieve file info")
|
||||
return
|
||||
}
|
||||
|
||||
if xslices.Any(processes, func(process types.Process) bool {
|
||||
info, err := process.Info()
|
||||
if err != nil {
|
||||
logrus.WithError(err).Error("Could not retrieve process info")
|
||||
}
|
||||
|
||||
return sameFile(exeInfo, info.Exe)
|
||||
}) {
|
||||
logrus.Infof("Waiting for %v to finish.", exeInfo.Name())
|
||||
time.Sleep(1 * time.Second)
|
||||
continue
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func sameFile(info os.FileInfo, path string) bool {
|
||||
pathInfo, err := os.Stat(path)
|
||||
if err != nil {
|
||||
logrus.WithError(err).WithField("file", path).Error("Could not retrieve file info")
|
||||
}
|
||||
|
||||
return os.SameFile(pathInfo, info)
|
||||
}
|
||||
|
||||
@ -1,58 +0,0 @@
|
||||
// Copyright (c) 2022 Proton AG
|
||||
//
|
||||
// This file is part of Proton Mail Bridge.
|
||||
//
|
||||
// Proton Mail Bridge is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Proton Mail Bridge is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/bradenaw/juniper/xslices"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestSliceContains(t *testing.T) {
|
||||
assert.True(t, sliceContains([]string{"a", "b", "c"}, "a"))
|
||||
assert.True(t, sliceContains([]int{1, 2, 3}, 2))
|
||||
assert.False(t, sliceContains([]string{"a", "b", "c"}, "A"))
|
||||
assert.False(t, sliceContains([]int{1, 2, 3}, 4))
|
||||
assert.False(t, sliceContains([]string{}, "a"))
|
||||
assert.True(t, sliceContains([]string{"a", "a"}, "a"))
|
||||
}
|
||||
|
||||
func TestFindAndStrip(t *testing.T) {
|
||||
list := []string{"a", "b", "c", "c", "b", "c"}
|
||||
|
||||
result, found := findAndStrip(list, "a")
|
||||
assert.True(t, found)
|
||||
assert.True(t, xslices.Equal(result, []string{"b", "c", "c", "b", "c"}))
|
||||
|
||||
result, found = findAndStrip(list, "c")
|
||||
assert.True(t, found)
|
||||
assert.True(t, xslices.Equal(result, []string{"a", "b", "b"}))
|
||||
|
||||
result, found = findAndStrip([]string{"c", "c", "c"}, "c")
|
||||
assert.True(t, found)
|
||||
assert.True(t, xslices.Equal(result, []string{}))
|
||||
|
||||
result, found = findAndStrip(list, "A")
|
||||
assert.False(t, found)
|
||||
assert.True(t, xslices.Equal(result, list))
|
||||
|
||||
result, found = findAndStrip([]string{}, "a")
|
||||
assert.False(t, found)
|
||||
assert.True(t, xslices.Equal(result, []string{}))
|
||||
}
|
||||
1
extern/vcpkg
vendored
1
extern/vcpkg
vendored
Submodule extern/vcpkg deleted from f93ba152d5
154
go.mod
154
go.mod
@ -1,102 +1,80 @@
|
||||
module github.com/ProtonMail/proton-bridge/v2
|
||||
|
||||
go 1.18
|
||||
go 1.15
|
||||
|
||||
// These dependencies are `replace`d below, so the version numbers should be ignored.
|
||||
// They are in a separate require block to highlight this.
|
||||
require (
|
||||
github.com/0xAX/notificator v0.0.0-20220220101646-ee9b8921e557
|
||||
github.com/Masterminds/semver/v3 v3.1.1
|
||||
github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20220824120805-4b6e5c587895
|
||||
github.com/ProtonMail/go-imap-id v0.0.0-20190926060100-f94a56b9ecde
|
||||
github.com/ProtonMail/go-rfc5322 v0.11.0
|
||||
github.com/ProtonMail/go-srp v0.0.5
|
||||
github.com/ProtonMail/go-vcard v0.0.0-20180326232728-33aaa0a0c8a5
|
||||
github.com/ProtonMail/gopenpgp/v2 v2.4.10
|
||||
github.com/PuerkitoBio/goquery v1.8.0
|
||||
github.com/abiosoft/ishell v2.0.0+incompatible
|
||||
github.com/allan-simon/go-singleinstance v0.0.0-20210120080615-d0997106ab37
|
||||
github.com/bradenaw/juniper v0.7.0
|
||||
github.com/cucumber/godog v0.12.5
|
||||
github.com/cucumber/messages-go/v16 v16.0.1
|
||||
github.com/docker/docker-credential-helpers v0.6.4
|
||||
github.com/elastic/go-sysinfo v1.8.1
|
||||
github.com/emersion/go-imap v1.2.1
|
||||
github.com/emersion/go-imap-appendlimit v0.0.0-20210907172056-e3baed77bbe4
|
||||
github.com/emersion/go-imap-move v0.0.0-20210907172020-fe4558f9c872
|
||||
github.com/emersion/go-imap-quota v0.0.0-20210203125329-619074823f3c
|
||||
github.com/emersion/go-imap-unselect v0.0.0-20210907172115-4c2c4843bf69
|
||||
github.com/emersion/go-message v0.16.0
|
||||
github.com/emersion/go-sasl v0.0.0-20211008083017-0b9dcfb154ac
|
||||
github.com/emersion/go-smtp v0.15.0
|
||||
github.com/emersion/go-textwrapper v0.0.0-20200911093747-65d896831594
|
||||
github.com/fatih/color v1.13.0
|
||||
github.com/getsentry/sentry-go v0.13.0
|
||||
github.com/go-resty/resty/v2 v2.7.0
|
||||
github.com/godbus/dbus v4.1.0+incompatible
|
||||
github.com/golang/mock v1.6.0
|
||||
github.com/google/go-cmp v0.5.8
|
||||
github.com/google/uuid v1.3.0
|
||||
github.com/hashicorp/go-multierror v1.1.1
|
||||
github.com/jaytaylor/html2text v0.0.0-20211105163654-bc68cce691ba
|
||||
github.com/keybase/go-keychain v0.0.0-20220610143837-c2ce06069005
|
||||
github.com/logrusorgru/aurora v2.0.3+incompatible
|
||||
github.com/miekg/dns v1.1.50
|
||||
github.com/nsf/jsondiff v0.0.0-20210926074059-1e845ec5d249
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/ricochet2200/go-disk-usage/du v0.0.0-20210707232629-ac9918953285
|
||||
github.com/sirupsen/logrus v1.9.0
|
||||
github.com/stretchr/testify v1.8.0
|
||||
github.com/urfave/cli/v2 v2.11.2
|
||||
github.com/vmihailenco/msgpack/v5 v5.3.5
|
||||
go.etcd.io/bbolt v1.3.6
|
||||
golang.org/x/exp v0.0.0-20220827204233-334a2380cb91
|
||||
golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b
|
||||
golang.org/x/sys v0.0.0-20220829200755-d48e67d00261
|
||||
golang.org/x/text v0.3.7
|
||||
google.golang.org/grpc v1.49.0
|
||||
google.golang.org/protobuf v1.28.1
|
||||
howett.net/plist v1.0.0
|
||||
github.com/docker/docker-credential-helpers v0.6.3
|
||||
github.com/emersion/go-imap v1.0.6
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/ProtonMail/bcrypt v0.0.0-20210511135022-227b4adcab57 // indirect
|
||||
github.com/ProtonMail/go-mime v0.0.0-20220302105931-303f85f7fe0f // indirect
|
||||
github.com/0xAX/notificator v0.0.0-20191016112426-3962a5ea8da1
|
||||
github.com/Masterminds/semver/v3 v3.1.0
|
||||
github.com/ProtonMail/bcrypt v0.0.0-20211005172633-e235017c1baf // indirect
|
||||
github.com/ProtonMail/go-autostart v0.0.0-20181114175602-c5272053443a
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20220623141421-5afb4c282135
|
||||
github.com/ProtonMail/go-imap-id v0.0.0-20190926060100-f94a56b9ecde
|
||||
github.com/ProtonMail/go-rfc5322 v0.8.0
|
||||
github.com/ProtonMail/go-srp v0.0.5
|
||||
github.com/ProtonMail/go-vcard v0.0.0-20180326232728-33aaa0a0c8a5
|
||||
github.com/ProtonMail/gopenpgp/v2 v2.4.7
|
||||
github.com/PuerkitoBio/goquery v1.5.1
|
||||
github.com/abiosoft/ishell v2.0.0+incompatible
|
||||
github.com/abiosoft/readline v0.0.0-20180607040430-155bce2042db // indirect
|
||||
github.com/andybalholm/cascadia v1.3.1 // indirect
|
||||
github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20220816024939-bc8df83d7b9d // indirect
|
||||
github.com/chzyer/test v1.0.0 // indirect
|
||||
github.com/cloudflare/circl v1.1.0 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
|
||||
github.com/cronokirby/saferith v0.33.0 // indirect
|
||||
github.com/cucumber/gherkin-go/v19 v19.0.3 // indirect
|
||||
github.com/danieljoos/wincred v1.1.0 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/elastic/go-windows v1.0.0 // indirect
|
||||
github.com/emersion/go-vcard v0.0.0-20220507122617-d4056df0ec4a // indirect
|
||||
github.com/allan-simon/go-singleinstance v0.0.0-20160830203053-79edcfdc2dfc
|
||||
github.com/chzyer/logex v1.1.10 // indirect
|
||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1 // indirect
|
||||
github.com/cucumber/godog v0.12.1
|
||||
github.com/cucumber/messages-go/v16 v16.0.1
|
||||
github.com/elastic/go-sysinfo v1.7.1
|
||||
github.com/elastic/go-windows v1.0.1 // indirect
|
||||
github.com/emersion/go-imap-appendlimit v0.0.0-20190308131241-25671c986a6a
|
||||
github.com/emersion/go-imap-move v0.0.0-20190710073258-6e5a51a5b342
|
||||
github.com/emersion/go-imap-quota v0.0.0-20210203125329-619074823f3c
|
||||
github.com/emersion/go-imap-unselect v0.0.0-20171113212723-b985794e5f26
|
||||
github.com/emersion/go-message v0.12.1-0.20201221184100-40c3f864532b
|
||||
github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21
|
||||
github.com/emersion/go-smtp v0.14.0
|
||||
github.com/emersion/go-textwrapper v0.0.0-20200911093747-65d896831594
|
||||
github.com/emersion/go-vcard v0.0.0-20190105225839-8856043f13c5 // indirect
|
||||
github.com/fatih/color v1.9.0
|
||||
github.com/flynn-archive/go-shlex v0.0.0-20150515145356-3f9db97f8568 // indirect
|
||||
github.com/gofrs/uuid v4.0.0+incompatible // indirect
|
||||
github.com/golang/protobuf v1.5.2 // indirect
|
||||
github.com/hashicorp/errwrap v1.0.0 // indirect
|
||||
github.com/hashicorp/go-immutable-radix v1.3.0 // indirect
|
||||
github.com/hashicorp/go-memdb v1.3.0 // indirect
|
||||
github.com/hashicorp/golang-lru v0.5.4 // indirect
|
||||
github.com/joeshaw/multierror v0.0.0-20140124173710-69b34d4ec901 // indirect
|
||||
github.com/mattn/go-colorable v0.1.11 // indirect
|
||||
github.com/mattn/go-isatty v0.0.14 // indirect
|
||||
github.com/getsentry/sentry-go v0.12.0
|
||||
github.com/go-resty/resty/v2 v2.6.0
|
||||
github.com/godbus/dbus v4.1.0+incompatible
|
||||
github.com/golang/mock v1.4.4
|
||||
github.com/google/go-cmp v0.5.5
|
||||
github.com/google/uuid v1.1.1
|
||||
github.com/hashicorp/go-multierror v1.1.0
|
||||
github.com/jameskeane/bcrypt v0.0.0-20120420032655-c3cd44c1e20f // indirect
|
||||
github.com/jaytaylor/html2text v0.0.0-20200412013138-3577fbdbcff7
|
||||
github.com/keybase/go-keychain v0.0.0
|
||||
github.com/kr/text v0.2.0 // indirect
|
||||
github.com/logrusorgru/aurora v2.0.3+incompatible
|
||||
github.com/mattn/go-runewidth v0.0.9 // indirect
|
||||
github.com/olekukonko/tablewriter v0.0.5 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084 // indirect
|
||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/miekg/dns v1.1.41
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
|
||||
github.com/nsf/jsondiff v0.0.0-20200515183724-f29ed568f4ce
|
||||
github.com/olekukonko/tablewriter v0.0.4 // indirect
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/prometheus/procfs v0.7.3 // indirect
|
||||
github.com/ricochet2200/go-disk-usage/du v0.0.0-20210707232629-ac9918953285
|
||||
github.com/sirupsen/logrus v1.7.0
|
||||
github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf // indirect
|
||||
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
|
||||
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 // indirect
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
|
||||
golang.org/x/tools v0.1.12 // indirect
|
||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
github.com/stretchr/testify v1.7.0
|
||||
github.com/therecipe/qt v0.0.0-20200701200531-7f61353ee73e
|
||||
github.com/therecipe/qt/internal/binding/files/docs/5.12.0 v0.0.0-20200904063919-c0c124a5770d // indirect
|
||||
github.com/therecipe/qt/internal/binding/files/docs/5.13.0 v0.0.0-20200904063919-c0c124a5770d // indirect
|
||||
github.com/urfave/cli/v2 v2.2.0
|
||||
github.com/vmihailenco/msgpack/v5 v5.1.3
|
||||
go.etcd.io/bbolt v1.3.6
|
||||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d // indirect
|
||||
golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4
|
||||
golang.org/x/sys v0.0.0-20220627191245-f75cf1eec38b
|
||||
golang.org/x/text v0.3.7
|
||||
howett.net/plist v1.0.0
|
||||
)
|
||||
|
||||
replace (
|
||||
|
||||
426
go.sum
426
go.sum
@ -11,86 +11,107 @@ cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqCl
|
||||
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
|
||||
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
|
||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||
github.com/0xAX/notificator v0.0.0-20220220101646-ee9b8921e557 h1:l6surSnJ3RP4qA1qmKJ+hQn3UjytosdoG27WGjrDlVs=
|
||||
github.com/0xAX/notificator v0.0.0-20220220101646-ee9b8921e557/go.mod h1:sTrmvD/TxuypdOERsDOS7SndZg0rzzcCi1b6wQMXUYM=
|
||||
github.com/0xAX/notificator v0.0.0-20191016112426-3962a5ea8da1 h1:j9HaafapDbPbGRDku6e/HRs6KBMcKHiWcm1/9Sbxnl4=
|
||||
github.com/0xAX/notificator v0.0.0-20191016112426-3962a5ea8da1/go.mod h1:NtXa9WwQsukMHZpjNakTTz0LArxvGYdPA9CjIcUSZ6s=
|
||||
github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc=
|
||||
github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs=
|
||||
github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno=
|
||||
github.com/CloudyKit/jet/v3 v3.0.0/go.mod h1:HKQPgSJmdK8hdoAbKUUWajkHyHo4RaU5rMdUywE7VMo=
|
||||
github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY=
|
||||
github.com/Masterminds/semver/v3 v3.1.0 h1:Y2lUDsFKVRSYGojLJ1yLxSXdMmMYTYls0rCvoqmMUQk=
|
||||
github.com/Masterminds/semver/v3 v3.1.0/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs=
|
||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||
github.com/ProtonMail/bcrypt v0.0.0-20210511135022-227b4adcab57 h1:pHA4K54ifoogVLunGGHi3xyF5Nz4x+Uh3dJuy3NwGQQ=
|
||||
github.com/ProtonMail/bcrypt v0.0.0-20210511135022-227b4adcab57/go.mod h1:HecWFHognK8GfRDGnFQbW/LiV7A3MX3gZVs45vk5h8I=
|
||||
github.com/ProtonMail/bcrypt v0.0.0-20211005172633-e235017c1baf h1:yc9daCCYUefEs69zUkSzubzjBbL+cmOXgnmt9Fyd9ug=
|
||||
github.com/ProtonMail/bcrypt v0.0.0-20211005172633-e235017c1baf/go.mod h1:o0ESU9p83twszAU8LBeJKFAAMX14tISa0yk4Oo5TOqo=
|
||||
github.com/ProtonMail/docker-credential-helpers v1.1.0 h1:+kvUIpwWcbtP3WFv5sSvkFn/XLzSqPOB5AAthuk9xPk=
|
||||
github.com/ProtonMail/docker-credential-helpers v1.1.0/go.mod h1:mK0aBveCxhnQ756AmaTfXMZDeULvheYVhF/MWMErN5g=
|
||||
github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a h1:D+aZah+k14Gn6kmL7eKxoo/4Dr/lK3ChBcwce2+SQP4=
|
||||
github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a/go.mod h1:oTGdE7/DlWIr23G0IKW3OXK9wZ5Hw1GGiaJFccTvZi4=
|
||||
github.com/ProtonMail/go-autostart v0.0.0-20181114175602-c5272053443a h1:fXK2KsfnkBV9Nh+9SKzHchYjuE9s0vI20JG1mbtEAcc=
|
||||
github.com/ProtonMail/go-autostart v0.0.0-20181114175602-c5272053443a/go.mod h1:oTGdE7/DlWIr23G0IKW3OXK9wZ5Hw1GGiaJFccTvZi4=
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo=
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20220822140716-1678d6eb0cbe/go.mod h1:UBYPn8k0D56RtnR8RFQMjmh4KrZzWJ5o7Z9SYjossQ8=
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20220824120805-4b6e5c587895 h1:NsReiLpErIPzRrnogAXYwSoU7txA977LjDGrbkewJbg=
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20220824120805-4b6e5c587895/go.mod h1:UBYPn8k0D56RtnR8RFQMjmh4KrZzWJ5o7Z9SYjossQ8=
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20211221144345-a4f6767435ab h1:5FiL/TCaiKCss/BLMIACDxxadYrx767l9kh0qYX+sLQ=
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20211221144345-a4f6767435ab/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo=
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20220113124808-70ae35bab23f/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo=
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20220623141421-5afb4c282135 h1:xDc/cFH/hwyr9KyWc0sm26lpsscqtfZBvU8NpRLHwJ0=
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20220623141421-5afb4c282135/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo=
|
||||
github.com/ProtonMail/go-imap v0.0.0-20201228133358-4db68cea0cac h1:2xU3QncAiS/W3UlWZTkbNKW5WkLzk6Egl1T0xX+sbjs=
|
||||
github.com/ProtonMail/go-imap v0.0.0-20201228133358-4db68cea0cac/go.mod h1:yKASt+C3ZiDAiCSssxg9caIckWF/JG7ZQTO7GAmvicU=
|
||||
github.com/ProtonMail/go-imap-id v0.0.0-20190926060100-f94a56b9ecde h1:5koQozTDELymYOyFbQ/VSubexAEXzDR8qGM5mO8GRdw=
|
||||
github.com/ProtonMail/go-imap-id v0.0.0-20190926060100-f94a56b9ecde/go.mod h1:795VPXcRUIQ9JyMNHP4el582VokQfippgjkQP3Gk0r0=
|
||||
github.com/ProtonMail/go-message v0.0.0-20210611055058-fabeff2ec753 h1:I8IsYA297x0QLU80G5I6aLYUu3JYNSpo8j5fkXtFDW0=
|
||||
github.com/ProtonMail/go-message v0.0.0-20210611055058-fabeff2ec753/go.mod h1:NBAn21zgCJ/52WLDyed18YvYFm5tEoeDauubFqLokM4=
|
||||
github.com/ProtonMail/go-mime v0.0.0-20190923161245-9b5a4261663a h1:W6RrgN/sTxg1msqzFFb+G80MFmpjMw61IU+slm+wln4=
|
||||
github.com/ProtonMail/go-mime v0.0.0-20190923161245-9b5a4261663a/go.mod h1:NYt+V3/4rEeDuaev/zw1zCq8uqVEuPHzDPo3OZrlGJ4=
|
||||
github.com/ProtonMail/go-mime v0.0.0-20220302105931-303f85f7fe0f h1:CGq7OieOz3wyQJ1fO8S0eO9TCW1JyvLrf8fhzz1i8ko=
|
||||
github.com/ProtonMail/go-mime v0.0.0-20220302105931-303f85f7fe0f/go.mod h1:NYt+V3/4rEeDuaev/zw1zCq8uqVEuPHzDPo3OZrlGJ4=
|
||||
github.com/ProtonMail/go-rfc5322 v0.11.0 h1:o5Obrm4DpmQEffvgsVqG6S4BKwC1Wat+hYwjIp2YcCY=
|
||||
github.com/ProtonMail/go-rfc5322 v0.11.0/go.mod h1:6oOKr0jXvpoE6pwTx/HukigQpX2J9WUf6h0auplrFTw=
|
||||
github.com/ProtonMail/go-rfc5322 v0.8.0 h1:7emrf75n3CDIduQflx7aT1nJa5h/kGsiFKUYX/+IAkU=
|
||||
github.com/ProtonMail/go-rfc5322 v0.8.0/go.mod h1:BwpTbkJxkMGkc+pC84AXZnwuWOisEULBpfPIyIKS/Us=
|
||||
github.com/ProtonMail/go-srp v0.0.1 h1:J0O9Zb5XTC6iDrB7feH41cu+TUEB+l7uHctXIK6oS2o=
|
||||
github.com/ProtonMail/go-srp v0.0.1/go.mod h1:Uvv5cqSGCs8MTZ8sbKiCkBnaB6/OA3eq2mc77tl2VVA=
|
||||
github.com/ProtonMail/go-srp v0.0.5 h1:xhUioxZgDbCnpo9JehyFhwwsn9JLWkUGfB0oiKXgiGg=
|
||||
github.com/ProtonMail/go-srp v0.0.5/go.mod h1:06iYHtLXW8vjLtccWj++x3MKy65sIT8yZd7nrJF49rs=
|
||||
github.com/ProtonMail/go-vcard v0.0.0-20180326232728-33aaa0a0c8a5 h1:Uga1DHFN4GUxuDQr0F71tpi8I9HqPIlZodZAI1lR6VQ=
|
||||
github.com/ProtonMail/go-vcard v0.0.0-20180326232728-33aaa0a0c8a5/go.mod h1:oeP9CMN+ajWp5jKp1kue5daJNwMMxLF+ujPaUIoJWlA=
|
||||
github.com/ProtonMail/gopenpgp/v2 v2.4.10 h1:EYgkxzwmQvsa6kxxkgP1AwzkFqKHscF2UINxaSn6rdI=
|
||||
github.com/ProtonMail/gopenpgp/v2 v2.4.10/go.mod h1:CTRA7/toc/4DxDy5Du4hPDnIZnJvXSeQ8LsRTOUJoyc=
|
||||
github.com/PuerkitoBio/goquery v1.8.0 h1:PJTF7AmFCFKk1N6V6jmKfrNH9tV5pNE6lZMkG0gta/U=
|
||||
github.com/PuerkitoBio/goquery v1.8.0/go.mod h1:ypIiRMtY7COPGk+I/YbZLbxsxn9g5ejnI2HSMtkjZvI=
|
||||
github.com/ProtonMail/gopenpgp/v2 v2.4.1 h1:b3El0zabaKi73u4sRnb3hOOUczuKuYpN8wnp7wRsZSc=
|
||||
github.com/ProtonMail/gopenpgp/v2 v2.4.1/go.mod h1:RFjoVjfhV8f78tjz/fLrp/OXkugL3QmWsiJq/fsQYA4=
|
||||
github.com/ProtonMail/gopenpgp/v2 v2.4.7 h1:V3xeelvXgJiZXZuPtSSE+uYbtPw4RmbmyPqXDAESPhg=
|
||||
github.com/ProtonMail/gopenpgp/v2 v2.4.7/go.mod h1:ZW1KxHNG6q5LMgFKf9Ap/d2eVYeyGf5+fAUEAjJWtmo=
|
||||
github.com/PuerkitoBio/goquery v1.5.1 h1:PSPBGne8NIUWw+/7vFBV+kG2J/5MOjbzc7154OaKCSE=
|
||||
github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc=
|
||||
github.com/Shopify/goreferrer v0.0.0-20181106222321-ec9c9a553398/go.mod h1:a1uqRtAwp2Xwc6WNPJEufxJ7fx3npB4UV/JOLmbu5I0=
|
||||
github.com/abiosoft/ishell v2.0.0+incompatible h1:zpwIuEHc37EzrsIYah3cpevrIc8Oma7oZPxr03tlmmw=
|
||||
github.com/abiosoft/ishell v2.0.0+incompatible/go.mod h1:HQR9AqF2R3P4XXpMpI0NAzgHf/aS6+zVXRj14cVk9qg=
|
||||
github.com/abiosoft/readline v0.0.0-20180607040430-155bce2042db h1:CjPUSXOiYptLbTdr1RceuZgSFDQ7U15ITERUGrUORx8=
|
||||
github.com/abiosoft/readline v0.0.0-20180607040430-155bce2042db/go.mod h1:rB3B4rKii8V21ydCbIzH5hZiCQE7f5E9SzUb/ZZx530=
|
||||
github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/allan-simon/go-singleinstance v0.0.0-20210120080615-d0997106ab37 h1:28uU3TtuvQ6KRndxg9TrC868jBWmSKgh0GTXkACCXmA=
|
||||
github.com/allan-simon/go-singleinstance v0.0.0-20210120080615-d0997106ab37/go.mod h1:6AXRstqK+32jeFmw89QGL2748+dj34Av4xc/I9oo9BY=
|
||||
github.com/andybalholm/cascadia v1.3.1 h1:nhxRkql1kdYCc8Snf7D5/D3spOX+dBgjA6u8x004T2c=
|
||||
github.com/andybalholm/cascadia v1.3.1/go.mod h1:R4bJ1UQfqADjvDa4P6HZHLh/3OxWWEqc0Sk8XGwHqvA=
|
||||
github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20220816024939-bc8df83d7b9d h1:0xIrH2lJbraclvJT3pvTf3u2oCAL60cAqiv4qRpz4EI=
|
||||
github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20220816024939-bc8df83d7b9d/go.mod h1:F7bn7fEU90QkQ3tnmaTx3LTKLEDqnwWODIYppRQ5hnY=
|
||||
github.com/allan-simon/go-singleinstance v0.0.0-20160830203053-79edcfdc2dfc h1:mZca0/HZ/XWXP9txkfdl2GH6mUzBqAlyJz3u5Lg8fuA=
|
||||
github.com/allan-simon/go-singleinstance v0.0.0-20160830203053-79edcfdc2dfc/go.mod h1:qqsTQiwdyqxU05iDCsi0oN3P4nrVxAmn8xCtODDSf/U=
|
||||
github.com/andybalholm/cascadia v1.1.0 h1:BuuO6sSfQNFRu1LppgbD25Hr2vLYW25JvxHs5zzsLTo=
|
||||
github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
|
||||
github.com/antlr/antlr4 v0.0.0-20201029161626-9a95f0cc3d7c h1:j/C2kxPfyE0d87/ggAjIsCV5Cdkqmjb+O0W8W+1J+IY=
|
||||
github.com/antlr/antlr4 v0.0.0-20201029161626-9a95f0cc3d7c/go.mod h1:T7PbCXFs94rrTttyxjbyT5+/1V8T2TYDejxUfHJjw1Y=
|
||||
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
|
||||
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
||||
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
|
||||
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
||||
github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
||||
github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
|
||||
github.com/bradenaw/juniper v0.7.0 h1:8JaJpY2Sm+EheEows6ZsS7s8ZM86Fa3yfaq5xXQH4SI=
|
||||
github.com/bradenaw/juniper v0.7.0/go.mod h1:Z2B7aJlQ7xbfWsnMLROj5t/5FQ94/MkIdKC30J4WvzI=
|
||||
github.com/bwesterb/go-ristretto v1.2.0/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||
github.com/chzyer/logex v1.2.1 h1:XHDu3E6q+gdHgsdTPH6ImJMIp436vR6MPtH8gP05QzM=
|
||||
github.com/chzyer/logex v1.2.1/go.mod h1:JLbx6lG2kDbNRFnfkgvh4eRJRPX1QCoOIWomwysCBrQ=
|
||||
github.com/chzyer/test v1.0.0 h1:p3BQDXSxOhOG0P9z6/hGnII4LGiEPOYBhs8asl/fC04=
|
||||
github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8=
|
||||
github.com/chzyer/logex v1.1.10 h1:Swpa1K6QvQznwJRcfTfQJmTE72DqScAa40E+fbHEXEE=
|
||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1 h1:q763qf9huN11kDQavWsoZXJNW3xEE4JJyHa5Q25/sd8=
|
||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cloudflare/circl v1.1.0 h1:bZgT/A+cikZnKIwn7xL2OBj012Bmvho/o6RpRvv3GKY=
|
||||
github.com/cloudflare/circl v1.1.0/go.mod h1:prBCrKB9DV4poKZY1l9zBXg2QJY7mvgRvtMxxK7fi4I=
|
||||
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM=
|
||||
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
|
||||
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||
github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
|
||||
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
||||
github.com/cpuguy83/go-md2man v1.0.10 h1:BSKMNlYxDvnunlTymqtgONjNnaRV1sTpcovwwjF22jk=
|
||||
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/cronokirby/saferith v0.31.0 h1:TIlhldetKLeGAb19bZvWiuwQEzfzwSPthDEyJ9Ah8xs=
|
||||
github.com/cronokirby/saferith v0.31.0/go.mod h1:QKJhjoqUtBsXCAVEjw38mFqoi7DebT7kthcD7UzbnoA=
|
||||
github.com/cronokirby/saferith v0.33.0 h1:TgoQlfsD4LIwx71+ChfRcIpjkw+RPOapDEVxa+LhwLo=
|
||||
github.com/cronokirby/saferith v0.33.0/go.mod h1:QKJhjoqUtBsXCAVEjw38mFqoi7DebT7kthcD7UzbnoA=
|
||||
github.com/cucumber/gherkin-go/v19 v19.0.3 h1:mMSKu1077ffLbTJULUfM5HPokgeBcIGboyeNUof1MdE=
|
||||
github.com/cucumber/gherkin-go/v19 v19.0.3/go.mod h1:jY/NP6jUtRSArQQJ5h1FXOUgk5fZK24qtE7vKi776Vw=
|
||||
github.com/cucumber/godog v0.12.5 h1:FZIy6VCfMbmGHts9qd6UjBMT9abctws/pQYO/ZcwOVs=
|
||||
github.com/cucumber/godog v0.12.5/go.mod h1:u6SD7IXC49dLpPN35kal0oYEjsXZWee4pW6Tm9t5pIc=
|
||||
github.com/cucumber/godog v0.12.1 h1:IhWVYFKDReM5WsuA9AuRLRPWOyvFNO9UBUKrNfLPais=
|
||||
github.com/cucumber/godog v0.12.1/go.mod h1:u6SD7IXC49dLpPN35kal0oYEjsXZWee4pW6Tm9t5pIc=
|
||||
github.com/cucumber/messages-go/v16 v16.0.0/go.mod h1:EJcyR5Mm5ZuDsKJnT2N9KRnBK30BGjtYotDKpwQ0v6g=
|
||||
github.com/cucumber/messages-go/v16 v16.0.1 h1:fvkpwsLgnIm0qugftrw2YwNlio+ABe2Iu94Ap8GMYIY=
|
||||
github.com/cucumber/messages-go/v16 v16.0.1/go.mod h1:EJcyR5Mm5ZuDsKJnT2N9KRnBK30BGjtYotDKpwQ0v6g=
|
||||
@ -101,93 +122,102 @@ github.com/danieljoos/wincred v1.1.0/go.mod h1:XYlo+eRTsVA9aHGp7NGjFkPla4m+DCL7h
|
||||
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/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dgraph-io/badger v1.6.0/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6psNgSztDR4=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||
github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
|
||||
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
||||
github.com/elastic/go-sysinfo v1.8.1 h1:4Yhj+HdV6WjbCRgGdZpPJ8lZQlXZLKDAeIkmQ/VRvi4=
|
||||
github.com/elastic/go-sysinfo v1.8.1/go.mod h1:JfllUnzoQV/JRYymbH3dO1yggI3mV2oTKSXsDHM+uIM=
|
||||
github.com/elastic/go-windows v1.0.0 h1:qLURgZFkkrYyTTkvYpsZIgf83AUsdIHfvlJaqaZ7aSY=
|
||||
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZifjYj7uP3BG/gKcuzL9xWVV/Y+cK33KM=
|
||||
github.com/elastic/go-sysinfo v1.7.1 h1:Wx4DSARcKLllpKT2TnFVdSUJOsybqMYCNQZq1/wO+s0=
|
||||
github.com/elastic/go-sysinfo v1.7.1/go.mod h1:i1ZYdU10oLNfRzq4vq62BEwD2fH8KaWh6eh0ikPT9F0=
|
||||
github.com/elastic/go-windows v1.0.0/go.mod h1:TsU0Nrp7/y3+VwE82FoZF8gC/XFg/Elz6CcloAxnPgU=
|
||||
github.com/emersion/go-imap-appendlimit v0.0.0-20210907172056-e3baed77bbe4 h1:U6LL6F1dYqXpVTwEbXhcfU8hgpNvmjB9xeOAiHN695o=
|
||||
github.com/emersion/go-imap-appendlimit v0.0.0-20210907172056-e3baed77bbe4/go.mod h1:ikgISoP7pRAolqsVP64yMteJa2FIpS6ju88eBT6K1yQ=
|
||||
github.com/emersion/go-imap-move v0.0.0-20210907172020-fe4558f9c872 h1:HGBfonz0q/zq7y3ew+4oy4emHSvk6bkmV0mdDG3E77M=
|
||||
github.com/emersion/go-imap-move v0.0.0-20210907172020-fe4558f9c872/go.mod h1:QuMaZcKFDVI0yCrnAbPLfbwllz1wtOrZH8/vZ5yzp4w=
|
||||
github.com/elastic/go-windows v1.0.1 h1:AlYZOldA+UJ0/2nBuqWdo90GFCgG9xuyw9SYzGUtJm0=
|
||||
github.com/elastic/go-windows v1.0.1/go.mod h1:FoVvqWSun28vaDQPbj2Elfc0JahhPB7WQEGa3c814Ss=
|
||||
github.com/emersion/go-imap-appendlimit v0.0.0-20190308131241-25671c986a6a h1:bMdSPm6sssuOFpIaveu3XGAijMS3Tq2S3EqFZmZxidc=
|
||||
github.com/emersion/go-imap-appendlimit v0.0.0-20190308131241-25671c986a6a/go.mod h1:ikgISoP7pRAolqsVP64yMteJa2FIpS6ju88eBT6K1yQ=
|
||||
github.com/emersion/go-imap-move v0.0.0-20190710073258-6e5a51a5b342 h1:5p1t3e1PomYgLWwEwhwEU5kVBwcyAcVrOpexv8AeZx0=
|
||||
github.com/emersion/go-imap-move v0.0.0-20190710073258-6e5a51a5b342/go.mod h1:QuMaZcKFDVI0yCrnAbPLfbwllz1wtOrZH8/vZ5yzp4w=
|
||||
github.com/emersion/go-imap-quota v0.0.0-20210203125329-619074823f3c h1:khcEdu1yFiZjBgi7gGnQiLhpSgghJ0YTnKD0l4EUqqc=
|
||||
github.com/emersion/go-imap-quota v0.0.0-20210203125329-619074823f3c/go.mod h1:iApyhIQBiU4XFyr+3kdJyyGqle82TbQyuP2o+OZHrV0=
|
||||
github.com/emersion/go-imap-unselect v0.0.0-20210907172115-4c2c4843bf69 h1:ltTnRlPdSMMb0a/pg7S31T3g+syYeSS5UVJtiR7ez1Y=
|
||||
github.com/emersion/go-imap-unselect v0.0.0-20210907172115-4c2c4843bf69/go.mod h1:+gnnZx3Mg3MnCzZrv0eZdp5puxXQUgGT/6N6L7ShKfM=
|
||||
github.com/emersion/go-imap-unselect v0.0.0-20171113212723-b985794e5f26 h1:FiSb8+XBQQSkcX3ubr+1tAtlRJBYaFmRZqOAweZ9Wy8=
|
||||
github.com/emersion/go-imap-unselect v0.0.0-20171113212723-b985794e5f26/go.mod h1:+gnnZx3Mg3MnCzZrv0eZdp5puxXQUgGT/6N6L7ShKfM=
|
||||
github.com/emersion/go-sasl v0.0.0-20191210011802-430746ea8b9b/go.mod h1:G/dpzLu16WtQpBfQ/z3LYiYJn3ZhKSGWn83fyoyQe/k=
|
||||
github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21 h1:OJyUGMJTzHTd1XQp98QTaHernxMYzRaOasRir9hUlFQ=
|
||||
github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21/go.mod h1:iL2twTeMvZnrg54ZoPDNfJaJaqy0xIQFuBdrLsmspwQ=
|
||||
github.com/emersion/go-sasl v0.0.0-20211008083017-0b9dcfb154ac h1:tn/OQ2PmwQ0XFVgAHfjlLyqMewry25Rz7jWnVoh4Ggs=
|
||||
github.com/emersion/go-sasl v0.0.0-20211008083017-0b9dcfb154ac/go.mod h1:iL2twTeMvZnrg54ZoPDNfJaJaqy0xIQFuBdrLsmspwQ=
|
||||
github.com/emersion/go-smtp v0.15.0 h1:3+hMGMGrqP/lqd7qoxZc1hTU8LY8gHV9RFGWlqSDmP8=
|
||||
github.com/emersion/go-smtp v0.15.0/go.mod h1:qm27SGYgoIPRot6ubfQ/GpiPy/g3PaZAVRxiO/sDUgQ=
|
||||
github.com/emersion/go-smtp v0.14.0 h1:RYW203p+EcPjL8Z/ZpT9lZ6iOc8MG1MQzEx1UKEkXlA=
|
||||
github.com/emersion/go-smtp v0.14.0/go.mod h1:qm27SGYgoIPRot6ubfQ/GpiPy/g3PaZAVRxiO/sDUgQ=
|
||||
github.com/emersion/go-textwrapper v0.0.0-20200911093747-65d896831594 h1:IbFBtwoTQyw0fIM5xv1HF+Y+3ZijDR839WMulgxCcUY=
|
||||
github.com/emersion/go-textwrapper v0.0.0-20200911093747-65d896831594/go.mod h1:aqO8z8wPrjkscevZJFVE1wXJrLpC5LtJG7fqLOsPb2U=
|
||||
github.com/emersion/go-vcard v0.0.0-20220507122617-d4056df0ec4a h1:cltZpe6s0SJtqK5c/5y2VrIYi8BAtDM6qjmiGYqfTik=
|
||||
github.com/emersion/go-vcard v0.0.0-20220507122617-d4056df0ec4a/go.mod h1:HMJKR5wlh/ziNp+sHEDV2ltblO4JD2+IdDOWtGcQBTM=
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/emersion/go-vcard v0.0.0-20190105225839-8856043f13c5 h1:n9qx98xiS5V4x2WIpPC2rr9mUM5ri9r/YhCEKbhCHro=
|
||||
github.com/emersion/go-vcard v0.0.0-20190105225839-8856043f13c5/go.mod h1:WIi9g8OKJQHXtQbx7GExlo6UAFaui9WDMYabJ+Be4WI=
|
||||
github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw=
|
||||
github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8=
|
||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w=
|
||||
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
|
||||
github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s=
|
||||
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
|
||||
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
|
||||
github.com/flynn-archive/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BMXYYRWTLOJKlh+lOBt6nUQgXAfB7oVIQt5cNreqSLI=
|
||||
github.com/flynn-archive/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:rZfgFAXFS/z/lEd6LJmf9HVZ1LkgYiHx5pHhV5DR16M=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/getsentry/sentry-go v0.13.0 h1:20dgTiUSfxRB/EhMPtxcL9ZEbM1ZdR+W/7f7NWD+xWo=
|
||||
github.com/getsentry/sentry-go v0.13.0/go.mod h1:EOsfu5ZdvKPfeHYV6pTVQnsjfp30+XA7//UooKNumH0=
|
||||
github.com/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc=
|
||||
github.com/getsentry/sentry-go v0.12.0 h1:era7g0re5iY13bHSdN/xMkyV+5zZppjRVQhZrXCaEIk=
|
||||
github.com/getsentry/sentry-go v0.12.0/go.mod h1:NSap0JBYWzHND8oMbyi0+XZhUalc1TBdRL1M71JZW2c=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3/go.mod h1:VJ0WA2NBN22VlZ2dKZQPAPnyWw5XTlK1KymzLKsr59s=
|
||||
github.com/gin-gonic/gin v1.4.0/go.mod h1:OW2EZn3DO8Ln9oIKOvM++LBO+5UPHJJDH72/q/3rZdM=
|
||||
github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98=
|
||||
github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w=
|
||||
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
|
||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||
github.com/go-resty/resty/v2 v2.7.0 h1:me+K9p3uhSmXtrBZ4k9jcEAfJmuC8IivWHwaLZwPrFY=
|
||||
github.com/go-resty/resty/v2 v2.7.0/go.mod h1:9PWDzw47qPphMRFfhsyk0NnSgvluHcljSMVIq3w7q0I=
|
||||
github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8=
|
||||
github.com/go-resty/resty/v2 v2.6.0 h1:joIR5PNLM2EFqqESUjCMGXrWmXNHEU9CEiK813oKYS4=
|
||||
github.com/go-resty/resty/v2 v2.6.0/go.mod h1:PwvJS6hvaPkjtjNg9ph+VrSD92bi5Zq73w/BIH7cC3Q=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo=
|
||||
github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
|
||||
github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM=
|
||||
github.com/godbus/dbus v4.1.0+incompatible h1:WqqLRTsQic3apZUK9qC5sGNfXthmPXzUZ7nQPrNITa4=
|
||||
github.com/godbus/dbus v4.1.0+incompatible/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw=
|
||||
github.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw=
|
||||
github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
|
||||
github.com/golang/mock v1.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.4.4 h1:l75CXGRSwbaYNpl/Z2X1XIIAMSCquvXgpVZDhwEIJsc=
|
||||
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
||||
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
||||
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
|
||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/gomodule/redigo v1.7.1-0.20190724094224-574c33c3df38/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4=
|
||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
|
||||
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||
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.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
|
||||
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
||||
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20190411002643-bd77b112433e h1:XWcjeEtTFTOVA9Fs1w7n2XBftk5ib4oZrhzWk0B+3eA=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20190411002643-bd77b112433e/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
|
||||
@ -204,8 +234,8 @@ github.com/hashicorp/go-memdb v1.3.0 h1:xdXq34gBOMEloa9rlGStLxmfX/dyIK8htOv36dQU
|
||||
github.com/hashicorp/go-memdb v1.3.0/go.mod h1:Mluclgwib3R93Hk5fxEfiRhB+6Dar64wWh71LpNSe3g=
|
||||
github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
|
||||
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
|
||||
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
|
||||
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
|
||||
github.com/hashicorp/go-multierror v1.1.0 h1:B9UzwGQJehnUY1yNrnwREHc3fGbC2xefo8g4TbElacI=
|
||||
github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA=
|
||||
github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
|
||||
github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
|
||||
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
|
||||
@ -213,6 +243,7 @@ github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/b
|
||||
github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/hashicorp/go-uuid v1.0.2 h1:cfejS+Tpcp13yd5nYHWDI6qVCny6wyX2Mt5SGur2IGE=
|
||||
github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
||||
github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=
|
||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
@ -223,45 +254,83 @@ github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO
|
||||
github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
|
||||
github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
|
||||
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/jaytaylor/html2text v0.0.0-20211105163654-bc68cce691ba h1:QFQpJdgbON7I0jr2hYW7Bs+XV0qjc3d5tZoDnRFnqTg=
|
||||
github.com/jaytaylor/html2text v0.0.0-20211105163654-bc68cce691ba/go.mod h1:CVKlgaMiht+LXvHG173ujK6JUhZXKb2u/BQtjPDIvyk=
|
||||
github.com/iris-contrib/blackfriday v2.0.0+incompatible/go.mod h1:UzZ2bDEoaSGPbkg6SAB4att1aAwTmVIx/5gCVqeyUdI=
|
||||
github.com/iris-contrib/go.uuid v2.0.0+incompatible/go.mod h1:iz2lgM/1UnEf1kP0L/+fafWORmlnuysV2EMP8MW+qe0=
|
||||
github.com/iris-contrib/jade v1.1.3/go.mod h1:H/geBymxJhShH5kecoiOCSssPX7QWYH7UaeZTSWddIk=
|
||||
github.com/iris-contrib/pongo2 v0.0.1/go.mod h1:Ssh+00+3GAZqSQb30AvBRNxBx7rf0GqwkjqxNd0u65g=
|
||||
github.com/iris-contrib/schema v0.0.1/go.mod h1:urYA3uvUNG1TIIjOSCzHr9/LmbQo8LrOcOqfqxa4hXw=
|
||||
github.com/jameskeane/bcrypt v0.0.0-20120420032655-c3cd44c1e20f/go.mod h1:u+9Snq0w+ZdYKi8BBoaxnEwWu0fY4Kvu9ByFpM51t1s=
|
||||
github.com/jaytaylor/html2text v0.0.0-20200412013138-3577fbdbcff7 h1:g0fAGBisHaEQ0TRq1iBvemFRf+8AEWEmBESSiWB3Vsc=
|
||||
github.com/jaytaylor/html2text v0.0.0-20200412013138-3577fbdbcff7/go.mod h1:CVKlgaMiht+LXvHG173ujK6JUhZXKb2u/BQtjPDIvyk=
|
||||
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
||||
github.com/joeshaw/multierror v0.0.0-20140124173710-69b34d4ec901 h1:rp+c0RAYOWj8l6qbCUTSiRLG/iKnW3K3/QfPPuSsBt4=
|
||||
github.com/joeshaw/multierror v0.0.0-20140124173710-69b34d4ec901/go.mod h1:Z86h9688Y0wesXCyonoVr47MasHilkuLMqGhRZ4Hpak=
|
||||
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
|
||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||
github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k=
|
||||
github.com/kataras/golog v0.0.10/go.mod h1:yJ8YKCmyL+nWjERB90Qwn+bdyBZsaQwU3bTVFgkFIp8=
|
||||
github.com/kataras/iris/v12 v12.1.8/go.mod h1:LMYy4VlP67TQ3Zgriz8RE2h2kMZV2SgMYbq3UhfoFmE=
|
||||
github.com/kataras/neffos v0.0.14/go.mod h1:8lqADm8PnbeFfL7CLXh1WHw53dG27MC3pgi2R1rmoTE=
|
||||
github.com/kataras/pio v0.0.2/go.mod h1:hAoW0t9UmXi4R5Oyq5Z4irTbaTsOemSrDGUtaTl7Dro=
|
||||
github.com/kataras/sitemap v0.0.5/go.mod h1:KY2eugMKiPwsJgx7+U103YZehfvNGOXURubcGyk0Bz8=
|
||||
github.com/keybase/go-keychain v0.0.0-20200502122510-cda31fe0c86d h1:gVjhBCfVGl32RIBooOANzfw+0UqX8HU+yPlMv8vypcg=
|
||||
github.com/keybase/go-keychain v0.0.0-20200502122510-cda31fe0c86d/go.mod h1:W6EbaYmb4RldPn0N3gvVHjY1wmU59kbymhW9NATWhwY=
|
||||
github.com/keybase/go-keychain v0.0.0-20211119201326-e02f34051621 h1:aMQ7pA4f06yOVXSulygyGvy4xA94fyzjUGs0iqQdMOI=
|
||||
github.com/keybase/go-keychain v0.0.0-20211119201326-e02f34051621/go.mod h1:enrU/ug069Om7vWxuFE6nikLI2BZNwevMiGSo43Kt5w=
|
||||
github.com/keybase/go.dbus v0.0.0-20200324223359-a94be52c0b03/go.mod h1:a8clEhrrGV/d76/f9r2I41BwANMihfZYV9C223vaxqE=
|
||||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/klauspost/compress v1.8.2/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
|
||||
github.com/klauspost/compress v1.9.7/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
|
||||
github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
|
||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/labstack/echo/v4 v4.5.0/go.mod h1:czIriw4a0C1dFun+ObrXp7ok03xON0N1awStJ6ArI7Y=
|
||||
github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k=
|
||||
github.com/logrusorgru/aurora v2.0.3+incompatible h1:tOpm7WcpBTn4fjmVfgpQq0EfczGlG91VSDkswnjF5A8=
|
||||
github.com/logrusorgru/aurora v2.0.3+incompatible/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=
|
||||
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||
github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-colorable v0.1.11 h1:nQ+aFkoE2TMGc0b68U2OKSexC+eq46+XwZzWXHRmPYs=
|
||||
github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
|
||||
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
|
||||
github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
|
||||
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
||||
github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
|
||||
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/mediocregopher/radix/v3 v3.4.2/go.mod h1:8FL3F6UQRXHXIBSPUs5h0RybMF8i4n7wVopoX3x7Bv8=
|
||||
github.com/microcosm-cc/bluemonday v1.0.2/go.mod h1:iVP4YcDBq+n/5fb23BhYFvIMq/leAFZyRl6bYmGDlGc=
|
||||
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
||||
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.41 h1:WMszZWJG0XmzbK9FEmzH2TVcqYzFesusSIB41b8KHxY=
|
||||
github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI=
|
||||
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
|
||||
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
@ -270,17 +339,29 @@ github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS4
|
||||
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
|
||||
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/moul/http2curl v1.0.0/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/nsf/jsondiff v0.0.0-20210926074059-1e845ec5d249 h1:NHrXEjTNQY7P0Zfx1aMrNhpgxHmow66XQtm0aQLY0AE=
|
||||
github.com/nsf/jsondiff v0.0.0-20210926074059-1e845ec5d249/go.mod h1:mpRZBD8SJ55OIICQ3iWH0Yz3cjzA61JdqMLoWXeB2+8=
|
||||
github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg=
|
||||
github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w=
|
||||
github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
|
||||
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||
github.com/nsf/jsondiff v0.0.0-20200515183724-f29ed568f4ce h1:RPclfga2SEJmgMmz2k+Mg7cowZ8yv4Trqw9UsJby758=
|
||||
github.com/nsf/jsondiff v0.0.0-20200515183724-f29ed568f4ce/go.mod h1:uFMI8w+ref4v2r9jz+c9i1IfIttS/OkmLfrk1jne5hs=
|
||||
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
|
||||
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
|
||||
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
|
||||
github.com/olekukonko/tablewriter v0.0.4 h1:vHD/YYe1Wolo78koG299f7V/VAS08c6IpCLn+Ejf/w8=
|
||||
github.com/olekukonko/tablewriter v0.0.4/go.mod h1:zq6QwlOf5SlnkVbMSr5EoBv3636FWnp+qbPhuoO21uA=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||
github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4=
|
||||
github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
@ -292,27 +373,34 @@ github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXP
|
||||
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
|
||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
||||
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084 h1:sofwID9zm4tzrgykg80hfFph1mryUeLRsUfoocVVmRY=
|
||||
github.com/prometheus/procfs v0.0.0-20190425082905-87a4384529e0/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU=
|
||||
github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
|
||||
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
||||
github.com/ricochet2200/go-disk-usage/du v0.0.0-20210707232629-ac9918953285 h1:d54EL9l+XteliUfUCGsEwwuk65dmmxX85VXF+9T6+50=
|
||||
github.com/ricochet2200/go-disk-usage/du v0.0.0-20210707232629-ac9918953285/go.mod h1:fxIDly1xtudczrZeOOlfaUvd2OPb2qZAPuWdU2BsBTk=
|
||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo=
|
||||
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
|
||||
github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q=
|
||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||
github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||
github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g=
|
||||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
||||
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
|
||||
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM=
|
||||
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||
github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
|
||||
@ -321,39 +409,60 @@ github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4k
|
||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
||||
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
|
||||
github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI=
|
||||
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
|
||||
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
|
||||
github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
|
||||
github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf h1:pvbZ0lM0XWPBqUKqFU8cmavspvIl9nulOYwdy6IFRRo=
|
||||
github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf/go.mod h1:RJID2RhlZKId02nZ62WenDCkgHFerpIOmW0iT7GKmXM=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0 h1:M2gUjqZET1qApGOWNSnZ49BAIMX4F/1plDv3+l31EJ4=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48=
|
||||
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
|
||||
github.com/therecipe/qt v0.0.0-20200701200531-7f61353ee73e h1:G0DQ/TRQyrEZjtLlLwevFjaRiG8eeCMlq9WXQ2OO2bk=
|
||||
github.com/therecipe/qt v0.0.0-20200701200531-7f61353ee73e/go.mod h1:SUUR2j3aE1z6/g76SdD6NwACEpvCxb3fvG82eKbD6us=
|
||||
github.com/therecipe/qt/internal/binding/files/docs/5.12.0 v0.0.0-20200904063919-c0c124a5770d h1:hAZyEG2swPRWjF0kqqdGERXUazYnRJdAk4a58f14z7Y=
|
||||
github.com/therecipe/qt/internal/binding/files/docs/5.12.0 v0.0.0-20200904063919-c0c124a5770d/go.mod h1:7m8PDYDEtEVqfjoUQc2UrFqhG0CDmoVJjRlQxexndFc=
|
||||
github.com/therecipe/qt/internal/binding/files/docs/5.13.0 v0.0.0-20200904063919-c0c124a5770d h1:AJRoBel/g9cDS+yE8BcN3E+TDD/xNAguG21aoR8DAIE=
|
||||
github.com/therecipe/qt/internal/binding/files/docs/5.13.0 v0.0.0-20200904063919-c0c124a5770d/go.mod h1:mH55Ek7AZcdns5KPp99O0bg+78el64YCYWHiQKrOdt4=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
github.com/urfave/cli/v2 v2.11.2 h1:FVfNg4m3vbjbBpLYxW//WjxUoHvJ9TlppXcqY9Q9ZfA=
|
||||
github.com/urfave/cli/v2 v2.11.2/go.mod h1:f8iq5LtQ/bLxafbdBSLPPNsgaW0l/2fYYEHhAyPlwvo=
|
||||
github.com/vmihailenco/msgpack/v5 v5.3.5 h1:5gO0H1iULLWGhs2H5tbAHIZTV8/cYafcFOr9znI5mJU=
|
||||
github.com/vmihailenco/msgpack/v5 v5.3.5/go.mod h1:7xyJ9e+0+9SaZT0Wt1RGleJXzli6Q/V5KbhBonMG9jc=
|
||||
github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g=
|
||||
github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds=
|
||||
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
|
||||
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
|
||||
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
|
||||
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
|
||||
github.com/urfave/cli/v2 v2.2.0 h1:JTTnM6wKzdA0Jqodd966MVj4vWbbquZykeX1sKbe2C4=
|
||||
github.com/urfave/cli/v2 v2.2.0/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ=
|
||||
github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4=
|
||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||
github.com/valyala/fasthttp v1.6.0/go.mod h1:FstJa9V+Pj9vQ7OJie2qMHdwemEDaDiSdBnvPM1Su9w=
|
||||
github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
|
||||
github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
|
||||
github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio=
|
||||
github.com/vmihailenco/msgpack/v5 v5.1.3 h1:FwC9KPjyW8OqTUqMt6rQw9y50vA2cTLXPKCcBCRbQgg=
|
||||
github.com/vmihailenco/msgpack/v5 v5.1.3/go.mod h1:C5gboKD0TJPqWDTVTtrQNfRbiBwHZGo8UTqP/9/XvLI=
|
||||
github.com/vmihailenco/tagparser v0.1.2 h1:gnjoVuB/kljJ5wICEEOpx98oXMWPLj22G67Vbd1qPqc=
|
||||
github.com/vmihailenco/tagparser v0.1.2/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI=
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
|
||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
|
||||
github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
|
||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU=
|
||||
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8=
|
||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
||||
github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI=
|
||||
github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg=
|
||||
github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM=
|
||||
github.com/yudai/pp v2.0.1+incompatible/go.mod h1:PuxR/8QJ7cyCkFp/aUDS+JY727OFEZkTdatxwunjIkc=
|
||||
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||
go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU=
|
||||
go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4=
|
||||
@ -364,21 +473,28 @@ go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/
|
||||
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190418165655-df01cb2cc480/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
|
||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191227163750-53104e6ec876/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 h1:7I4JAnoQBe7ZtJcBaYHi5UtiO8tQHbUSXxL+pnGRANg=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4 h1:kUhD7nTDoI3fVd9G4ORWrbV5NY0liEs/Jg2pv5f+bBA=
|
||||
golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d h1:sK3txAijHtOK88l68nt020reeT1ZdKLIYetKl95FzVY=
|
||||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||
golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9tZUw9qufEGTyX1+7lmHxV5q5G4=
|
||||
golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
|
||||
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
|
||||
golang.org/x/exp v0.0.0-20220827204233-334a2380cb91 h1:tnebWN09GYg9OLPss1KXj8txwZc6X6uMr6VFdcGNbHw=
|
||||
golang.org/x/exp v0.0.0-20220827204233-334a2380cb91/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE=
|
||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
@ -395,11 +511,10 @@ golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKG
|
||||
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
|
||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.1.1-0.20191209134235-331c550502dd/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
@ -407,18 +522,23 @@ golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73r
|
||||
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190327091125-710a502c58a2/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190420063019-afa5a82059c6/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/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-20191209160850-c0dbc17a3553/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-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
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-20210916014120-12bc252f5db8/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211029224645-99673261e6eb/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b h1:ZmngSVLe/wycRns9MKikG9OWIEjGcGAkacif7oYQaUY=
|
||||
golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
|
||||
golang.org/x/net v0.0.0-20211008194852-3b03d305991f h1:1scJEYZBaF48BaG6tYbtxmLcXqwYGSfGcMoStTqkkIw=
|
||||
golang.org/x/net v0.0.0-20211008194852-3b03d305991f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4 h1:HVyaeDAYux4pnY+D/SiwmLOR36ewZ4iGQIIrtnuCjFA=
|
||||
golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
@ -427,37 +547,55 @@ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJ
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 h1:uVc8UZUe6tr40fFVnUP5Oj+veunVezqYl9z7DYw9xzw=
|
||||
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/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-20190222072716-a9d3bda3a223/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-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190419153524-e8e3143a4f4a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191025021431-6c3a3bfe00ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/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-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220829200755-d48e67d00261 h1:v6hYoSR9T5oet+pMXwUWkbiVqx/63mlHjefrHmxwfeY=
|
||||
golang.org/x/sys v0.0.0-20220829200755-d48e67d00261/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e h1:fLOSk5Q00efkSvAm+4xcoXD+RRmLmmulPn5I3Y9F2EM=
|
||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220111092808-5a964db01320 h1:0jf+tOCoZ3LyutmCOWpVni1chK4VfFLhRsDK7MhqGRY=
|
||||
golang.org/x/sys v0.0.0-20220111092808-5a964db01320/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220627191245-f75cf1eec38b h1:2n253B2r0pYSmEV+UNCQoPfU/FiaizQEK5Gu4Bq4JE8=
|
||||
golang.org/x/sys v0.0.0-20220627191245-f75cf1eec38b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
|
||||
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.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
@ -468,17 +606,20 @@ 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/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20181221001348-537d06c36207/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190327201419-c70d86f8b7cf/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190420181800-aa740d480789/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
@ -487,15 +628,12 @@ golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtn
|
||||
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/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-20200117012304-6edc0a871e69 h1:yBHHx+XZqXJBm6Exke3N7V9gnlsyXxoCPEb1yVenjfk=
|
||||
golang.org/x/tools v0.0.0-20200117012304-6edc0a871e69/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
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.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||
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=
|
||||
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
|
||||
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
|
||||
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
|
||||
@ -514,49 +652,39 @@ google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98
|
||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||
google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
|
||||
google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 h1:+kGHl1aib/qcwaRi1CbqBZ1rk19r85MNUf8HaBghugY=
|
||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.49.0 h1:WTLtQzmQori5FUH25Pq4WT22oCsv8USpQ+F6rqtsmxw=
|
||||
google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
||||
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
||||
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
|
||||
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE=
|
||||
gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/RRjR0eouCJSH80/M2Y=
|
||||
gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/ini.v1 v1.51.1/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA=
|
||||
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
|
||||
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.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
|
||||
gopkg.in/yaml.v2 v2.2.1/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.v3 v3.0.0-20191120175047-4206685974f2/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.0-20200615113413-eeeca48fe776 h1:tQIYjPdBoyREyB9XMu+nnTclpTYkz2zFM+lzLJFO4gQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||
howett.net/plist v0.0.0-20181124034731-591f970eefbb/go.mod h1:vMygbs4qMhSZSc4lCUl2OEE+rDiIIJAIdR4m7MiMcm0=
|
||||
howett.net/plist v1.0.0 h1:7CrbWYbPPO/PyNy38b2EB/+gYbjCe2DXBxgtOOZbSQM=
|
||||
howett.net/plist v1.0.0/go.mod h1:lqaXoTrLY4hg8tnEzNru53gicrbv7rrk+2xJA/7hw9g=
|
||||
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
||||
|
||||
@ -24,7 +24,6 @@ package api
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/ProtonMail/proton-bridge/v2/internal/bridge"
|
||||
"github.com/ProtonMail/proton-bridge/v2/internal/config/settings"
|
||||
@ -58,9 +57,8 @@ func (api *apiServer) ListenAndServe() {
|
||||
|
||||
addr := api.getAddress()
|
||||
server := &http.Server{
|
||||
Addr: addr,
|
||||
Handler: mux,
|
||||
ReadHeaderTimeout: 5 * time.Second, // fix gosec G112 (vulnerability to [Slowloris](https://www.cloudflare.com/en-gb/learning/ddos/ddos-attack-tools/slowloris/) attack).
|
||||
Addr: addr,
|
||||
Handler: mux,
|
||||
}
|
||||
|
||||
log.Info("API listening at ", addr)
|
||||
|
||||
@ -17,14 +17,13 @@
|
||||
|
||||
// Package base implements a common application base currently shared by bridge and IE.
|
||||
// The base includes the following:
|
||||
// - access to standard filesystem locations like config, cache, logging dirs
|
||||
// - an extensible crash handler
|
||||
// - versioned cache directory
|
||||
// - persistent settings
|
||||
// - event listener
|
||||
// - credentials store
|
||||
// - pmapi Manager
|
||||
//
|
||||
// - access to standard filesystem locations like config, cache, logging dirs
|
||||
// - an extensible crash handler
|
||||
// - versioned cache directory
|
||||
// - persistent settings
|
||||
// - event listener
|
||||
// - credentials store
|
||||
// - pmapi Manager
|
||||
// In addition, the base initialises logging and reacts to command line arguments
|
||||
// which control the log verbosity and enable cpu/memory profiling.
|
||||
package base
|
||||
@ -94,12 +93,10 @@ type Base struct {
|
||||
TLS *tls.TLS
|
||||
Autostart *autostart.App
|
||||
|
||||
Name string // the app's name
|
||||
usage string // the app's usage description
|
||||
command string // the command used to launch the app (either the exe path or the launcher path)
|
||||
restart bool // whether the app is currently set to restart
|
||||
launcher string // launcher to be used if not set in args
|
||||
mainExecutable string // mainExecutable the main executable process.
|
||||
Name string // the app's name
|
||||
usage string // the app's usage description
|
||||
command string // the command used to launch the app (either the exe path or the launcher path)
|
||||
restart bool // whether the app is currently set to restart
|
||||
|
||||
teardown []func() error // actions to perform when app is exiting
|
||||
}
|
||||
@ -270,9 +267,6 @@ func New( //nolint:funlen
|
||||
// By default, the command is the app's executable.
|
||||
// This can be changed at runtime by using the "--launcher" flag.
|
||||
command: exe,
|
||||
// By default, the command is the app's executable.
|
||||
// This can be changed at runtime by summoning the SetMainExecutable gRPC call.
|
||||
mainExecutable: exe,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@ -328,16 +322,6 @@ func (b *Base) SetToRestart() {
|
||||
b.restart = true
|
||||
}
|
||||
|
||||
func (b *Base) ForceLauncher(launcher string) {
|
||||
b.launcher = launcher
|
||||
b.setupLauncher(launcher)
|
||||
}
|
||||
|
||||
func (b *Base) SetMainExecutable(exe string) {
|
||||
logrus.Info("Main Executable set to ", exe)
|
||||
b.mainExecutable = exe
|
||||
}
|
||||
|
||||
// AddTeardownAction adds an action to perform during app teardown.
|
||||
func (b *Base) AddTeardownAction(fn func() error) {
|
||||
b.teardown = append(b.teardown, fn)
|
||||
@ -351,7 +335,10 @@ func (b *Base) wrapMainLoop(appMainLoop func(*Base, *cli.Context) error) cli.Act
|
||||
// If launcher was used to start the app, use that for restart
|
||||
// and autostart.
|
||||
if launcher := c.String(FlagLauncher); launcher != "" {
|
||||
b.setupLauncher(launcher)
|
||||
b.command = launcher
|
||||
// Bridge supports no-window option which we should use
|
||||
// for autostart.
|
||||
b.Autostart.Exec = []string{launcher, "--" + FlagNoWindow}
|
||||
}
|
||||
|
||||
if c.Bool(flagCPUProfile) {
|
||||
@ -415,10 +402,3 @@ func (b *Base) doTeardown() error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *Base) setupLauncher(launcher string) {
|
||||
b.command = launcher
|
||||
// Bridge supports no-window option which we should use
|
||||
// for autostart.
|
||||
b.Autostart.Exec = []string{launcher, "--" + FlagNoWindow}
|
||||
}
|
||||
|
||||
@ -38,12 +38,6 @@ func (b *Base) restartApp(crash bool) error {
|
||||
args = os.Args[1:]
|
||||
}
|
||||
|
||||
if b.launcher != "" {
|
||||
args = forceLauncherFlag(args, b.launcher)
|
||||
}
|
||||
|
||||
args = append(args, "--wait", b.mainExecutable)
|
||||
|
||||
logrus.
|
||||
WithField("command", b.command).
|
||||
WithField("args", args).
|
||||
@ -84,29 +78,3 @@ func incrementRestartFlag(args []string) []string {
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
// forceLauncherFlag replace or add the launcher args with the one set in the app.
|
||||
func forceLauncherFlag(args []string, launcher string) []string {
|
||||
res := append([]string{}, args...)
|
||||
|
||||
hasFlag := false
|
||||
|
||||
for k, v := range res {
|
||||
if v != "--launcher" {
|
||||
continue
|
||||
}
|
||||
|
||||
if k+1 >= len(res) {
|
||||
continue
|
||||
}
|
||||
|
||||
hasFlag = true
|
||||
res[k+1] = launcher
|
||||
}
|
||||
|
||||
if !hasFlag {
|
||||
res = append(res, "--launcher", launcher)
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
@ -19,12 +19,14 @@
|
||||
package bridge
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"time"
|
||||
|
||||
"github.com/ProtonMail/proton-bridge/v2/internal/api"
|
||||
"github.com/ProtonMail/proton-bridge/v2/internal/app/base"
|
||||
pkgBridge "github.com/ProtonMail/proton-bridge/v2/internal/bridge"
|
||||
"github.com/ProtonMail/proton-bridge/v2/internal/config/settings"
|
||||
pkgTLS "github.com/ProtonMail/proton-bridge/v2/internal/config/tls"
|
||||
"github.com/ProtonMail/proton-bridge/v2/internal/constants"
|
||||
"github.com/ProtonMail/proton-bridge/v2/internal/frontend"
|
||||
"github.com/ProtonMail/proton-bridge/v2/internal/frontend/types"
|
||||
@ -50,7 +52,7 @@ const (
|
||||
)
|
||||
|
||||
func New(base *base.Base) *cli.App {
|
||||
app := base.NewApp(main)
|
||||
app := base.NewApp(mailLoop)
|
||||
|
||||
app.Flags = append(app.Flags, []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
@ -70,7 +72,15 @@ func New(base *base.Base) *cli.App {
|
||||
return app
|
||||
}
|
||||
|
||||
func main(b *base.Base, c *cli.Context) error { //nolint:funlen
|
||||
func mailLoop(b *base.Base, c *cli.Context) error { //nolint:funlen
|
||||
tlsConfig, err := loadTLSConfig(b)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// GODT-1481: Always turn off reporting of unencrypted recipient in v2.
|
||||
b.Settings.SetBool(settings.ReportOutgoingNoEncKey, false)
|
||||
|
||||
cache, cacheErr := loadMessageCache(b)
|
||||
if cacheErr != nil {
|
||||
logrus.WithError(cacheErr).Error("Could not load local cache.")
|
||||
@ -88,8 +98,6 @@ func main(b *base.Base, c *cli.Context) error { //nolint:funlen
|
||||
b.SentryReporter,
|
||||
b.CrashHandler,
|
||||
b.Listener,
|
||||
b.TLS,
|
||||
b.UserAgent,
|
||||
cache,
|
||||
builder,
|
||||
b.CM,
|
||||
@ -101,11 +109,6 @@ func main(b *base.Base, c *cli.Context) error { //nolint:funlen
|
||||
imapBackend := imap.NewIMAPBackend(b.CrashHandler, b.Listener, b.Cache, b.Settings, bridge)
|
||||
smtpBackend := smtp.NewSMTPBackend(b.CrashHandler, b.Listener, b.Settings, bridge)
|
||||
|
||||
tlsConfig, err := bridge.GetTLSConfig()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if cacheErr != nil {
|
||||
bridge.AddError(pkgBridge.ErrLocalCacheUnavailable)
|
||||
}
|
||||
@ -149,16 +152,23 @@ func main(b *base.Base, c *cli.Context) error { //nolint:funlen
|
||||
case c.Bool(flagNonInteractive):
|
||||
return <-(make(chan error)) // Block forever.
|
||||
default:
|
||||
frontendMode = "grpc"
|
||||
frontendMode = "qt"
|
||||
}
|
||||
|
||||
f := frontend.New(
|
||||
constants.Version,
|
||||
constants.BuildVersion,
|
||||
b.Name,
|
||||
frontendMode,
|
||||
!c.Bool(base.FlagNoWindow),
|
||||
b.CrashHandler,
|
||||
b.Locations,
|
||||
b.Settings,
|
||||
b.Listener,
|
||||
b.Updater,
|
||||
b.UserAgent,
|
||||
bridge,
|
||||
smtpBackend,
|
||||
b,
|
||||
)
|
||||
|
||||
@ -175,6 +185,44 @@ func main(b *base.Base, c *cli.Context) error { //nolint:funlen
|
||||
return f.Loop()
|
||||
}
|
||||
|
||||
func loadTLSConfig(b *base.Base) (*tls.Config, error) {
|
||||
if !b.TLS.HasCerts() {
|
||||
if err := generateTLSCerts(b); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
tlsConfig, err := b.TLS.GetConfig()
|
||||
if err == nil {
|
||||
return tlsConfig, nil
|
||||
}
|
||||
|
||||
logrus.WithError(err).Error("Failed to load TLS config, regenerating certificates")
|
||||
|
||||
if err := generateTLSCerts(b); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return b.TLS.GetConfig()
|
||||
}
|
||||
|
||||
func generateTLSCerts(b *base.Base) error {
|
||||
template, err := pkgTLS.NewTLSTemplate()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to generate TLS template")
|
||||
}
|
||||
|
||||
if err := b.TLS.GenerateCerts(template); err != nil {
|
||||
return errors.Wrap(err, "failed to generate TLS certs")
|
||||
}
|
||||
|
||||
if err := b.TLS.InstallCerts(); err != nil {
|
||||
return errors.Wrap(err, "failed to install TLS certs")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func checkAndHandleUpdate(u types.Updater, f frontend.Frontend, autoUpdate bool) {
|
||||
log := logrus.WithField("pkg", "app/bridge")
|
||||
version, err := u.Check()
|
||||
|
||||
@ -27,8 +27,6 @@ import (
|
||||
"github.com/Masterminds/semver/v3"
|
||||
"github.com/ProtonMail/go-autostart"
|
||||
"github.com/ProtonMail/proton-bridge/v2/internal/config/settings"
|
||||
"github.com/ProtonMail/proton-bridge/v2/internal/config/tls"
|
||||
"github.com/ProtonMail/proton-bridge/v2/internal/config/useragent"
|
||||
"github.com/ProtonMail/proton-bridge/v2/internal/constants"
|
||||
"github.com/ProtonMail/proton-bridge/v2/internal/metrics"
|
||||
"github.com/ProtonMail/proton-bridge/v2/internal/sentry"
|
||||
@ -54,27 +52,22 @@ type Bridge struct {
|
||||
clientManager pmapi.Manager
|
||||
updater Updater
|
||||
versioner Versioner
|
||||
tls *tls.TLS
|
||||
userAgent *useragent.UserAgent
|
||||
cacheProvider CacheProvider
|
||||
autostart *autostart.App
|
||||
// Bridge's global errors list.
|
||||
errors []error
|
||||
|
||||
isAllMailVisible bool
|
||||
isFirstStart bool
|
||||
lastVersion string
|
||||
isFirstStart bool
|
||||
lastVersion string
|
||||
}
|
||||
|
||||
func New( //nolint:funlen
|
||||
func New(
|
||||
locations Locator,
|
||||
cacheProvider CacheProvider,
|
||||
setting SettingsProvider,
|
||||
sentryReporter *sentry.Reporter,
|
||||
panicHandler users.PanicHandler,
|
||||
eventListener listener.Listener,
|
||||
tls *tls.TLS,
|
||||
userAgent *useragent.UserAgent,
|
||||
cache cache.Cache,
|
||||
builder *message.Builder,
|
||||
clientManager pmapi.Manager,
|
||||
@ -99,18 +92,15 @@ func New( //nolint:funlen
|
||||
)
|
||||
|
||||
b := &Bridge{
|
||||
Users: u,
|
||||
locations: locations,
|
||||
settings: setting,
|
||||
clientManager: clientManager,
|
||||
updater: updater,
|
||||
versioner: versioner,
|
||||
tls: tls,
|
||||
userAgent: userAgent,
|
||||
cacheProvider: cacheProvider,
|
||||
autostart: autostart,
|
||||
isFirstStart: false,
|
||||
isAllMailVisible: setting.GetBool(settings.IsAllMailVisible),
|
||||
Users: u,
|
||||
locations: locations,
|
||||
settings: setting,
|
||||
clientManager: clientManager,
|
||||
updater: updater,
|
||||
versioner: versioner,
|
||||
cacheProvider: cacheProvider,
|
||||
autostart: autostart,
|
||||
isFirstStart: false,
|
||||
}
|
||||
|
||||
if setting.GetBool(settings.FirstStartKey) {
|
||||
@ -312,14 +302,3 @@ func (b *Bridge) GetLastVersion() string {
|
||||
func (b *Bridge) IsFirstStart() bool {
|
||||
return b.isFirstStart
|
||||
}
|
||||
|
||||
// IsAllMailVisible can be called extensively by IMAP. Therefore, it is better
|
||||
// to cache the value instead of reading from settings file.
|
||||
func (b *Bridge) IsAllMailVisible() bool {
|
||||
return b.isAllMailVisible
|
||||
}
|
||||
|
||||
func (b *Bridge) SetIsAllMailVisible(isVisible bool) {
|
||||
b.settings.SetBool(settings.IsAllMailVisible, isVisible)
|
||||
b.isAllMailVisible = isVisible
|
||||
}
|
||||
|
||||
@ -1,70 +0,0 @@
|
||||
// Copyright (c) 2022 Proton AG
|
||||
//
|
||||
// This file is part of Proton Mail Bridge.
|
||||
//
|
||||
// Proton Mail Bridge is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Proton Mail Bridge is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
package bridge
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/ProtonMail/proton-bridge/v2/internal/clientconfig"
|
||||
"github.com/ProtonMail/proton-bridge/v2/internal/config/settings"
|
||||
"github.com/ProtonMail/proton-bridge/v2/internal/config/useragent"
|
||||
)
|
||||
|
||||
func (b *Bridge) ConfigureAppleMail(userID, address string) (bool, error) {
|
||||
user, err := b.GetUser(userID)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if address == "" {
|
||||
address = user.GetPrimaryAddress()
|
||||
}
|
||||
|
||||
username := address
|
||||
addresses := address
|
||||
|
||||
if user.IsCombinedAddressMode() {
|
||||
username = user.GetPrimaryAddress()
|
||||
addresses = strings.Join(user.GetAddresses(), ",")
|
||||
}
|
||||
|
||||
var (
|
||||
restart = false
|
||||
smtpSSL = b.settings.GetBool(settings.SMTPSSLKey)
|
||||
)
|
||||
|
||||
// If configuring apple mail for Catalina or newer, users should use SSL.
|
||||
if useragent.IsCatalinaOrNewer() && !smtpSSL {
|
||||
smtpSSL = true
|
||||
restart = true
|
||||
b.settings.SetBool(settings.SMTPSSLKey, true)
|
||||
}
|
||||
|
||||
if err := (&clientconfig.AppleMail{}).Configure(
|
||||
Host,
|
||||
b.settings.GetInt(settings.IMAPPortKey),
|
||||
b.settings.GetInt(settings.SMTPPortKey),
|
||||
false, smtpSSL,
|
||||
username, addresses,
|
||||
user.GetBridgePassword(),
|
||||
); err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return restart, nil
|
||||
}
|
||||
@ -1,30 +0,0 @@
|
||||
// Copyright (c) 2022 Proton AG
|
||||
//
|
||||
// This file is part of Proton Mail Bridge.
|
||||
//
|
||||
// Proton Mail Bridge is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Proton Mail Bridge is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
package bridge
|
||||
|
||||
func (b *Bridge) ProvideLogsPath() (string, error) {
|
||||
return b.locations.ProvideLogsPath()
|
||||
}
|
||||
|
||||
func (b *Bridge) GetLicenseFilePath() string {
|
||||
return b.locations.GetLicenseFilePath()
|
||||
}
|
||||
|
||||
func (b *Bridge) GetDependencyLicensesLink() string {
|
||||
return b.locations.GetDependencyLicensesLink()
|
||||
}
|
||||
@ -1,64 +0,0 @@
|
||||
// Copyright (c) 2022 Proton AG
|
||||
//
|
||||
// This file is part of Proton Mail Bridge.
|
||||
//
|
||||
// Proton Mail Bridge is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Proton Mail Bridge is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
package bridge
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
|
||||
pkgTLS "github.com/ProtonMail/proton-bridge/v2/internal/config/tls"
|
||||
"github.com/pkg/errors"
|
||||
logrus "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func (b *Bridge) GetTLSConfig() (*tls.Config, error) {
|
||||
if !b.tls.HasCerts() {
|
||||
if err := b.generateTLSCerts(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
tlsConfig, err := b.tls.GetConfig()
|
||||
if err == nil {
|
||||
return tlsConfig, nil
|
||||
}
|
||||
|
||||
logrus.WithError(err).Error("Failed to load TLS config, regenerating certificates")
|
||||
|
||||
if err := b.generateTLSCerts(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return b.tls.GetConfig()
|
||||
}
|
||||
|
||||
func (b *Bridge) generateTLSCerts() error {
|
||||
template, err := pkgTLS.NewTLSTemplate()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to generate TLS template")
|
||||
}
|
||||
|
||||
if err := b.tls.GenerateCerts(template); err != nil {
|
||||
return errors.Wrap(err, "failed to generate TLS certs")
|
||||
}
|
||||
|
||||
if err := b.tls.InstallCerts(); err != nil {
|
||||
return errors.Wrap(err, "failed to install TLS certs")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@ -20,18 +20,13 @@ package bridge
|
||||
import (
|
||||
"github.com/Masterminds/semver/v3"
|
||||
|
||||
"github.com/ProtonMail/proton-bridge/v2/internal/config/settings"
|
||||
"github.com/ProtonMail/proton-bridge/v2/internal/updater"
|
||||
)
|
||||
|
||||
type Locator interface {
|
||||
ProvideLogsPath() (string, error)
|
||||
|
||||
GetLicenseFilePath() string
|
||||
GetDependencyLicensesLink() string
|
||||
|
||||
Clear() error
|
||||
ClearUpdates() error
|
||||
ProvideLogsPath() (string, error)
|
||||
}
|
||||
|
||||
type CacheProvider interface {
|
||||
@ -41,14 +36,11 @@ type CacheProvider interface {
|
||||
}
|
||||
|
||||
type SettingsProvider interface {
|
||||
Get(key settings.Key) string
|
||||
Set(key settings.Key, value string)
|
||||
|
||||
GetBool(key settings.Key) bool
|
||||
SetBool(key settings.Key, val bool)
|
||||
|
||||
GetInt(key settings.Key) int
|
||||
SetInt(key settings.Key, val int)
|
||||
Get(key string) string
|
||||
Set(key string, value string)
|
||||
GetBool(key string) bool
|
||||
SetBool(key string, val bool)
|
||||
GetInt(key string) int
|
||||
}
|
||||
|
||||
type Updater interface {
|
||||
|
||||
@ -1,26 +0,0 @@
|
||||
// Copyright (c) 2022 Proton AG
|
||||
//
|
||||
// This file is part of Proton Mail Bridge.
|
||||
//
|
||||
// Proton Mail Bridge is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Proton Mail Bridge is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
package bridge
|
||||
|
||||
func (b *Bridge) GetCurrentUserAgent() string {
|
||||
return b.userAgent.String()
|
||||
}
|
||||
|
||||
func (b *Bridge) SetCurrentPlatform(platform string) {
|
||||
b.userAgent.SetPlatform(platform)
|
||||
}
|
||||
@ -30,9 +30,9 @@ import (
|
||||
)
|
||||
|
||||
type keyValueStore struct {
|
||||
vals map[Key]string
|
||||
path string
|
||||
lock *sync.RWMutex
|
||||
cache map[string]string
|
||||
path string
|
||||
lock *sync.RWMutex
|
||||
}
|
||||
|
||||
// newKeyValueStore returns loaded preferences.
|
||||
@ -48,14 +48,14 @@ func newKeyValueStore(path string) *keyValueStore {
|
||||
}
|
||||
|
||||
func (p *keyValueStore) load() error {
|
||||
if p.vals != nil {
|
||||
if p.cache != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
p.lock.Lock()
|
||||
defer p.lock.Unlock()
|
||||
|
||||
p.vals = make(map[Key]string)
|
||||
p.cache = map[string]string{}
|
||||
|
||||
f, err := os.Open(p.path)
|
||||
if err != nil {
|
||||
@ -63,18 +63,18 @@ func (p *keyValueStore) load() error {
|
||||
}
|
||||
defer f.Close() //nolint:errcheck,gosec
|
||||
|
||||
return json.NewDecoder(f).Decode(&p.vals)
|
||||
return json.NewDecoder(f).Decode(&p.cache)
|
||||
}
|
||||
|
||||
func (p *keyValueStore) save() error {
|
||||
if p.vals == nil {
|
||||
if p.cache == nil {
|
||||
return errors.New("cannot save preferences: cache is nil")
|
||||
}
|
||||
|
||||
p.lock.Lock()
|
||||
defer p.lock.Unlock()
|
||||
|
||||
b, err := json.MarshalIndent(p.vals, "", "\t")
|
||||
b, err := json.MarshalIndent(p.cache, "", "\t")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -82,24 +82,24 @@ func (p *keyValueStore) save() error {
|
||||
return ioutil.WriteFile(p.path, b, 0o600)
|
||||
}
|
||||
|
||||
func (p *keyValueStore) setDefault(key Key, value string) {
|
||||
func (p *keyValueStore) setDefault(key, value string) {
|
||||
if p.Get(key) == "" {
|
||||
p.Set(key, value)
|
||||
}
|
||||
}
|
||||
|
||||
func (p *keyValueStore) Get(key Key) string {
|
||||
func (p *keyValueStore) Get(key string) string {
|
||||
p.lock.RLock()
|
||||
defer p.lock.RUnlock()
|
||||
|
||||
return p.vals[key]
|
||||
return p.cache[key]
|
||||
}
|
||||
|
||||
func (p *keyValueStore) GetBool(key Key) bool {
|
||||
func (p *keyValueStore) GetBool(key string) bool {
|
||||
return p.Get(key) == "true"
|
||||
}
|
||||
|
||||
func (p *keyValueStore) GetInt(key Key) int {
|
||||
func (p *keyValueStore) GetInt(key string) int {
|
||||
if p.Get(key) == "" {
|
||||
return 0
|
||||
}
|
||||
@ -112,7 +112,7 @@ func (p *keyValueStore) GetInt(key Key) int {
|
||||
return value
|
||||
}
|
||||
|
||||
func (p *keyValueStore) GetFloat64(key Key) float64 {
|
||||
func (p *keyValueStore) GetFloat64(key string) float64 {
|
||||
if p.Get(key) == "" {
|
||||
return 0
|
||||
}
|
||||
@ -125,9 +125,9 @@ func (p *keyValueStore) GetFloat64(key Key) float64 {
|
||||
return value
|
||||
}
|
||||
|
||||
func (p *keyValueStore) Set(key Key, value string) {
|
||||
func (p *keyValueStore) Set(key, value string) {
|
||||
p.lock.Lock()
|
||||
p.vals[key] = value
|
||||
p.cache[key] = value
|
||||
p.lock.Unlock()
|
||||
|
||||
if err := p.save(); err != nil {
|
||||
@ -135,7 +135,7 @@ func (p *keyValueStore) Set(key Key, value string) {
|
||||
}
|
||||
}
|
||||
|
||||
func (p *keyValueStore) SetBool(key Key, value bool) {
|
||||
func (p *keyValueStore) SetBool(key string, value bool) {
|
||||
if value {
|
||||
p.Set(key, "true")
|
||||
} else {
|
||||
@ -143,10 +143,10 @@ func (p *keyValueStore) SetBool(key Key, value bool) {
|
||||
}
|
||||
}
|
||||
|
||||
func (p *keyValueStore) SetInt(key Key, value int) {
|
||||
func (p *keyValueStore) SetInt(key string, value int) {
|
||||
p.Set(key, strconv.Itoa(value))
|
||||
}
|
||||
|
||||
func (p *keyValueStore) SetFloat64(key Key, value float64) {
|
||||
func (p *keyValueStore) SetFloat64(key string, value float64) {
|
||||
p.Set(key, fmt.Sprintf("%v", value))
|
||||
}
|
||||
|
||||
@ -25,38 +25,36 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
type Key string
|
||||
|
||||
// Keys of preferences in JSON file.
|
||||
const (
|
||||
FirstStartKey Key = "first_time_start"
|
||||
FirstStartGUIKey Key = "first_time_start_gui"
|
||||
LastHeartbeatKey Key = "last_heartbeat"
|
||||
APIPortKey Key = "user_port_api"
|
||||
IMAPPortKey Key = "user_port_imap"
|
||||
SMTPPortKey Key = "user_port_smtp"
|
||||
SMTPSSLKey Key = "user_ssl_smtp"
|
||||
AllowProxyKey Key = "allow_proxy"
|
||||
AutostartKey Key = "autostart"
|
||||
AutoUpdateKey Key = "autoupdate"
|
||||
CookiesKey Key = "cookies"
|
||||
LastVersionKey Key = "last_used_version"
|
||||
UpdateChannelKey Key = "update_channel"
|
||||
RolloutKey Key = "rollout"
|
||||
PreferredKeychainKey Key = "preferred_keychain"
|
||||
CacheEnabledKey Key = "cache_enabled"
|
||||
CacheCompressionKey Key = "cache_compression"
|
||||
CacheLocationKey Key = "cache_location"
|
||||
CacheMinFreeAbsKey Key = "cache_min_free_abs"
|
||||
CacheMinFreeRatKey Key = "cache_min_free_rat"
|
||||
CacheConcurrencyRead Key = "cache_concurrent_read"
|
||||
CacheConcurrencyWrite Key = "cache_concurrent_write"
|
||||
IMAPWorkers Key = "imap_workers"
|
||||
FetchWorkers Key = "fetch_workers"
|
||||
AttachmentWorkers Key = "attachment_workers"
|
||||
ColorScheme Key = "color_scheme"
|
||||
RebrandingMigrationKey Key = "rebranding_migrated"
|
||||
IsAllMailVisible Key = "is_all_mail_visible"
|
||||
FirstStartKey = "first_time_start"
|
||||
FirstStartGUIKey = "first_time_start_gui"
|
||||
LastHeartbeatKey = "last_heartbeat"
|
||||
APIPortKey = "user_port_api"
|
||||
IMAPPortKey = "user_port_imap"
|
||||
SMTPPortKey = "user_port_smtp"
|
||||
SMTPSSLKey = "user_ssl_smtp"
|
||||
AllowProxyKey = "allow_proxy"
|
||||
AutostartKey = "autostart"
|
||||
AutoUpdateKey = "autoupdate"
|
||||
CookiesKey = "cookies"
|
||||
ReportOutgoingNoEncKey = "report_outgoing_email_without_encryption"
|
||||
LastVersionKey = "last_used_version"
|
||||
UpdateChannelKey = "update_channel"
|
||||
RolloutKey = "rollout"
|
||||
PreferredKeychainKey = "preferred_keychain"
|
||||
CacheEnabledKey = "cache_enabled"
|
||||
CacheCompressionKey = "cache_compression"
|
||||
CacheLocationKey = "cache_location"
|
||||
CacheMinFreeAbsKey = "cache_min_free_abs"
|
||||
CacheMinFreeRatKey = "cache_min_free_rat"
|
||||
CacheConcurrencyRead = "cache_concurrent_read"
|
||||
CacheConcurrencyWrite = "cache_concurrent_write"
|
||||
IMAPWorkers = "imap_workers"
|
||||
FetchWorkers = "fetch_workers"
|
||||
AttachmentWorkers = "attachment_workers"
|
||||
ColorScheme = "color_scheme"
|
||||
RebrandingMigrationKey = "rebranding_migrated"
|
||||
)
|
||||
|
||||
type Settings struct {
|
||||
@ -89,6 +87,7 @@ func (s *Settings) setDefaultValues() {
|
||||
s.setDefault(AllowProxyKey, "true")
|
||||
s.setDefault(AutostartKey, "true")
|
||||
s.setDefault(AutoUpdateKey, "true")
|
||||
s.setDefault(ReportOutgoingNoEncKey, "false")
|
||||
s.setDefault(LastVersionKey, "")
|
||||
s.setDefault(UpdateChannelKey, "")
|
||||
s.setDefault(RolloutKey, fmt.Sprintf("%v", rand.Float64())) //nolint:gosec // G404 It is OK to use weak random number generator here
|
||||
@ -111,6 +110,4 @@ func (s *Settings) setDefaultValues() {
|
||||
|
||||
// By default, stick to STARTTLS. If the user uses catalina+applemail they'll have to change to SSL.
|
||||
s.setDefault(SMTPSSLKey, "false")
|
||||
|
||||
s.setDefault(IsAllMailVisible, "true")
|
||||
}
|
||||
|
||||
@ -24,24 +24,18 @@ import (
|
||||
"github.com/Masterminds/semver/v3"
|
||||
)
|
||||
|
||||
// IsCatalinaOrNewer checks whether the host is macOS Catalina 10.15.x or higher.
|
||||
// IsCatalinaOrNewer checks whether the host is MacOS Catalina 10.15.x or higher.
|
||||
func IsCatalinaOrNewer() bool {
|
||||
return isThisDarwinNewerOrEqual(getMinCatalina())
|
||||
}
|
||||
|
||||
// IsBigSurOrNewer checks whether the host is macOS BigSur 10.16.x or higher.
|
||||
// IsBigSurOrNewer checks whether the host is MacOS BigSur 10.16.x or higher.
|
||||
func IsBigSurOrNewer() bool {
|
||||
return isThisDarwinNewerOrEqual(getMinBigSur())
|
||||
}
|
||||
|
||||
// IsVenturaOrNewer checks whether the host is macOS BigSur 13.x or higher.
|
||||
func IsVenturaOrNewer() bool {
|
||||
return isThisDarwinNewerOrEqual(getMinVentura())
|
||||
}
|
||||
|
||||
func getMinCatalina() *semver.Version { return semver.MustParse("19.0.0") }
|
||||
func getMinBigSur() *semver.Version { return semver.MustParse("20.0.0") }
|
||||
func getMinVentura() *semver.Version { return semver.MustParse("22.0.0") }
|
||||
|
||||
func isThisDarwinNewerOrEqual(minVersion *semver.Version) bool {
|
||||
if runtime.GOOS != "darwin" {
|
||||
|
||||
@ -24,9 +24,6 @@ const VendorName = "protonmail"
|
||||
|
||||
//nolint:gochecknoglobals
|
||||
var (
|
||||
// Version of the build.
|
||||
FullAppName = ""
|
||||
|
||||
// Version of the build.
|
||||
Version = ""
|
||||
|
||||
|
||||
@ -38,6 +38,7 @@ const (
|
||||
InternetOff = "internetOff"
|
||||
InternetOn = "internetOn"
|
||||
SecondInstanceEvent = "secondInstance"
|
||||
OutgoingNoEncEvent = "outgoingNoEncryption"
|
||||
NoActiveKeyForRecipientEvent = "noActiveKeyForRecipient"
|
||||
UpgradeApplicationEvent = "upgradeApplication"
|
||||
TLSCertIssue = "tlsCertPinningIssue"
|
||||
|
||||
3
internal/frontend/.gitignore
vendored
3
internal/frontend/.gitignore
vendored
@ -9,6 +9,3 @@ rcc.qrc
|
||||
rcc_cgo_*.go
|
||||
*.qmlc
|
||||
|
||||
# Generated file
|
||||
bridge-gui/bridge-gui/Version.h
|
||||
bridge-gui/bridge-gui/Resources.rc
|
||||
|
||||
@ -1,88 +0,0 @@
|
||||
# Copyright (c) 2022 Proton AG
|
||||
#
|
||||
# This file is part of Proton Mail Bridge.
|
||||
#
|
||||
# Proton Mail Bridge is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Proton Mail Bridge is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
include_guard()
|
||||
|
||||
|
||||
if (NOT DEFINED BRIDGE_REPO_ROOT)
|
||||
message(FATAL_ERROR "BRIDGE_REPO_ROOT is not defined.")
|
||||
endif()
|
||||
message(STATUS "BRIDGE_REPO_ROOT is ${BRIDGE_REPO_ROOT}")
|
||||
|
||||
#*****************************************************************************************************************************************************
|
||||
# Bridge version
|
||||
#*****************************************************************************************************************************************************
|
||||
if (NOT DEFINED BRIDGE_APP_VERSION)
|
||||
if (WIN32)
|
||||
find_program(POWERSHELL_EXE powershell.exe)
|
||||
if (NOT POWERSHELL_EXE)
|
||||
message(FATAL_ERROR "PowerShell could not be found.")
|
||||
endif()
|
||||
execute_process(COMMAND "${POWERSHELL_EXE}" -ExecutionPolicy Bypass "${BRIDGE_REPO_ROOT}/utils/bridge_app_version.ps1"
|
||||
OUTPUT_VARIABLE BRIDGE_APP_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE COMMAND_ERROR_IS_FATAL ANY)
|
||||
else()
|
||||
execute_process(COMMAND "${BRIDGE_REPO_ROOT}/utils/bridge_app_version.sh"
|
||||
OUTPUT_VARIABLE BRIDGE_APP_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE COMMAND_ERROR_IS_FATAL ANY)
|
||||
endif()
|
||||
if (NOT BRIDGE_APP_VERSION)
|
||||
message(FATAL_ERROR "Could not determine BRIDGE_APP_VERSION.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
||||
#****************************************************************************************************************************************************
|
||||
# vcpkg, toolchain, and architecture
|
||||
#****************************************************************************************************************************************************
|
||||
# We rely on vcpkg for to get gRPC / Protobuf
|
||||
# run build.sh / build.ps1 to get gRPC / Protobuf and dependencies installed.
|
||||
|
||||
set(VCPKG_ROOT "${BRIDGE_REPO_ROOT}/extern/vcpkg")
|
||||
message(STATUS "VCPKG_ROOT is ${VCPKG_ROOT}")
|
||||
if (WIN32)
|
||||
find_program(VCPKG_EXE "${VCPKG_ROOT}/vcpkg.exe")
|
||||
else()
|
||||
find_program(VCPKG_EXE "${VCPKG_ROOT}/vcpkg")
|
||||
endif()
|
||||
if (NOT VCPKG_EXE)
|
||||
message(FATAL_ERROR "vcpkg is not installed. Run build.sh (macOS/Linux) or build.ps1 (Windows) first.")
|
||||
endif()
|
||||
|
||||
# For now we support only a single architecture for macOS (ARM64 or x86_64). We need to investigate how to build universal binaries with vcpkg.
|
||||
if (APPLE)
|
||||
if (NOT DEFINED CMAKE_OSX_ARCHITECTURES)
|
||||
execute_process(COMMAND "uname" "-m" OUTPUT_VARIABLE UNAME_RESULT OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
set(CMAKE_OSX_ARCHITECTURES ${UNAME_RESULT} CACHE STRING "osx_architectures")
|
||||
endif()
|
||||
|
||||
if (CMAKE_OSX_ARCHITECTURES STREQUAL "arm64")
|
||||
message(STATUS "Building for Apple Silicon Mac computers")
|
||||
set(VCPKG_TARGET_TRIPLET arm64-osx)
|
||||
elseif (CMAKE_OSX_ARCHITECTURES STREQUAL "x86_64")
|
||||
message(STATUS "Building for Intel based Mac computers")
|
||||
set(VCPKG_TARGET_TRIPLET x64-osx)
|
||||
else ()
|
||||
message(FATAL_ERROR "Unknown value for CMAKE_OSX_ARCHITECTURE. Please use one of \"arm64\" and \"x86_64\". Multiple architectures are not supported.")
|
||||
endif ()
|
||||
endif()
|
||||
|
||||
if (WIN32)
|
||||
message(STATUS "Building for Intel x64 Windows computers")
|
||||
set(VCPKG_TARGET_TRIPLET x64-windows)
|
||||
endif()
|
||||
|
||||
set(CMAKE_TOOLCHAIN_FILE "${VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake" CACHE STRING "toolchain")
|
||||
@ -1,32 +0,0 @@
|
||||
# Copyright (c) 2022 Proton AG
|
||||
#
|
||||
# This file is part of Proton Mail Bridge.
|
||||
#
|
||||
# Proton Mail Bridge is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Proton Mail Bridge is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
cmake_minimum_required(VERSION 3.22)
|
||||
|
||||
|
||||
#*****************************************************************************************************************************************************
|
||||
# Project
|
||||
#*****************************************************************************************************************************************************
|
||||
set(BRIDGE_REPO_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/../../..")
|
||||
include("BridgeSetup.cmake")
|
||||
|
||||
project(frontend)
|
||||
|
||||
add_subdirectory(bridgepp)
|
||||
add_subdirectory(bridge-gui)
|
||||
add_subdirectory(bridge-gui-tester)
|
||||
@ -1,53 +0,0 @@
|
||||
# bridge-gui
|
||||
|
||||
bridge-gui is the graphical user interface for Bridge. It's a C++ [Qt](https://www.qt.io) application that
|
||||
communicates with the bridge executable via gRPC remote procedure call, on a local-only TLS-secured connection.
|
||||
|
||||
# Components
|
||||
|
||||
bridge-gui consists in 3 components:
|
||||
|
||||
- **bridge-gui**: The Bridge-GUI application itself. It's a QML Qt application that implements the bridge
|
||||
[gRPC](https://www.grpc.io) service to communicate and interact with the bridge application written in
|
||||
[Go](https://go.dev).
|
||||
- **bridge-gui-tester**: A Qt widgets test application that offers a dummy gRPC server implementing the Bridge gRPC
|
||||
service. It can be used as a debugging and development tool, as it can simulate the server side (bridge) portion of
|
||||
the gRPC service.
|
||||
- **bridgepp**: bridgepp (for bridge++) is a C++ static library that contains the code shared by bridge-gui and
|
||||
bridge-gui-tester.
|
||||
|
||||
# Bridge gRPC service
|
||||
|
||||
The bridge gRPC service that allows communications between bridge-gui, and the bridge Go application (or
|
||||
bridge-gui-tester) is defined in `../grpc/bridge.proto`.
|
||||
|
||||
# Supported platforms
|
||||
|
||||
bridge-gui runs on the same platforms as the bridge app:
|
||||
|
||||
- Linux x64.
|
||||
- macOS x64 and Apple Silicon.
|
||||
- Windows x64.
|
||||
|
||||
# Requirements:
|
||||
|
||||
- A C++ development toolchain ([GCC](https://gcc.gnu.org)/[Clang](https://clang.llvm.org)/
|
||||
[MSVC](https://docs.microsoft.com/en-us/cpp/?view=msvc-170), [CMake](https://cmake.org),
|
||||
[Ninja](https://ninja-build.org)). An easy way to get all the needed tools is to use a modern IDE such
|
||||
as [CLion](https://www.jetbrains.com/clion/), [Qt Creator](https://www.qt.io/product/development-tools) or
|
||||
[Visual Studio Code](https://code.visualstudio.com) that will check and install or use their bundled versions
|
||||
of the tools.
|
||||
- [Qt 6](https://www.qt.io/download-open-source). Use the online installer to install the latest stable
|
||||
release of Qt for your platform and compiler.
|
||||
|
||||
# First build
|
||||
|
||||
bridge-gui uses [vcpkg](https://vcpkg.io/en/index.html), Microsoft multi-platform C/C++ dependency manager to get
|
||||
the source code and build gRPC and its dependencies (protobuf, zlib, ...). vcpkg is managed as a git submodule
|
||||
in `extern/vcpkg`,relative to the root of the bridge source tree. A pair of scripts is provided to perform
|
||||
the initialization of vcpkg, the retrieval and compilation of gRPC and a first build of the bridge-gui project
|
||||
components:
|
||||
|
||||
- `build.sh`: a shell script to use on macOS and Linux.
|
||||
- `build.ps1`: a [PowerShell](https://docs.microsoft.com/en-us/powershell/) script for Windows.
|
||||
|
||||
@ -1,106 +0,0 @@
|
||||
// Copyright (c) 2022 Proton AG
|
||||
//
|
||||
// This file is part of Proton Mail Bridge.
|
||||
//
|
||||
// Proton Mail Bridge is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Proton Mail Bridge is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
#include "AppController.h"
|
||||
#include "GRPCService.h"
|
||||
#include <bridgepp/GRPC/GRPCUtils.h>
|
||||
#include <bridgepp/Exception/Exception.h>
|
||||
#include "MainWindow.h"
|
||||
#include <bridgepp/Log/Log.h>
|
||||
|
||||
|
||||
using namespace bridgepp;
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return A reference to the application controller.
|
||||
//****************************************************************************************************************************************************
|
||||
AppController &app()
|
||||
{
|
||||
static AppController app;
|
||||
return app;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
//
|
||||
//****************************************************************************************************************************************************
|
||||
AppController::AppController()
|
||||
: log_(std::make_unique<Log>())
|
||||
, bridgeGUILog_(std::make_unique<Log>())
|
||||
, grpc_(std::make_unique<GRPCService>())
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
//
|
||||
//****************************************************************************************************************************************************
|
||||
AppController::~AppController() // NOLINT(modernize-use-equals-default): implementation in cpp file is required because of forward declaration of Log in header
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] mainWindow The main window.
|
||||
//****************************************************************************************************************************************************
|
||||
void AppController::setMainWindow(MainWindow *mainWindow)
|
||||
{
|
||||
mainWindow_ = mainWindow;
|
||||
grpc_->connectProxySignals();
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return The main window.
|
||||
//****************************************************************************************************************************************************
|
||||
MainWindow &AppController::mainWindow()
|
||||
{
|
||||
if (!mainWindow_)
|
||||
throw Exception("mainWindow has not yet been registered.");
|
||||
return *mainWindow_;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return A reference to the log.
|
||||
//****************************************************************************************************************************************************
|
||||
bridgepp::Log &AppController::log()
|
||||
{
|
||||
return *log_;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return A reference to the bridge-gui log.
|
||||
//****************************************************************************************************************************************************
|
||||
bridgepp::Log &AppController::bridgeGUILog()
|
||||
{
|
||||
return *bridgeGUILog_;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return A reference to the gRPC service.
|
||||
//****************************************************************************************************************************************************
|
||||
GRPCService &AppController::grpc()
|
||||
{
|
||||
return *grpc_;
|
||||
}
|
||||
@ -1,63 +0,0 @@
|
||||
// Copyright (c) 2022 Proton AG
|
||||
//
|
||||
// This file is part of Proton Mail Bridge.
|
||||
//
|
||||
// Proton Mail Bridge is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Proton Mail Bridge is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
#ifndef BRIDGE_GUI_TESTER_APP_CONTROLLER_H
|
||||
#define BRIDGE_GUI_TESTER_APP_CONTROLLER_H
|
||||
|
||||
|
||||
class MainWindow;
|
||||
class GRPCService;
|
||||
namespace grpc { class StreamEvent; }
|
||||
namespace bridgepp { class Log; }
|
||||
|
||||
|
||||
//**********************************************************************************************************************
|
||||
/// \brief Application controller class
|
||||
//**********************************************************************************************************************
|
||||
class AppController : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public: // member functions.
|
||||
friend AppController &app();
|
||||
|
||||
AppController(AppController const &) = delete; ///< Disabled copy-constructor.
|
||||
AppController(AppController &&) = delete; ///< Disabled assignment copy-constructor.
|
||||
~AppController() override; ///< Destructor.
|
||||
AppController &operator=(AppController const &) = delete; ///< Disabled assignment operator.
|
||||
AppController &operator=(AppController &&) = delete; ///< Disabled move assignment operator.
|
||||
void setMainWindow(MainWindow *mainWindow); ///< Set the main window.
|
||||
MainWindow &mainWindow(); ///< Return the main window.
|
||||
bridgepp::Log &log(); ///< Return a reference to the log.
|
||||
bridgepp::Log &bridgeGUILog(); ///< Return a reference to the bridge-gui log.
|
||||
GRPCService &grpc(); ///< Return a reference to the gRPC service.
|
||||
|
||||
private: // member functions.
|
||||
AppController(); ///< Default constructor.
|
||||
|
||||
private: // data members.
|
||||
MainWindow *mainWindow_ { nullptr }; ///< The main window.
|
||||
std::unique_ptr<bridgepp::Log> log_; ///< The log.
|
||||
std::unique_ptr<bridgepp::Log> bridgeGUILog_; ///< The bridge-gui log.
|
||||
std::unique_ptr<GRPCService> grpc_; ///< The gRPC service.
|
||||
};
|
||||
|
||||
|
||||
AppController &app(); ///< Return a reference to the app controller.
|
||||
|
||||
|
||||
#endif // BRIDGE_GUI_TESTER_APP_CONTROLLER_H
|
||||
@ -1,90 +0,0 @@
|
||||
# Copyright (c) 2022 Proton AG
|
||||
#
|
||||
# This file is part of Proton Mail Bridge.
|
||||
#
|
||||
# Proton Mail Bridge is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Proton Mail Bridge is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
cmake_minimum_required(VERSION 3.22)
|
||||
|
||||
|
||||
set(BRIDGE_REPO_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/../../../..")
|
||||
include(../BridgeSetup.cmake)
|
||||
|
||||
|
||||
#*****************************************************************************************************************************************************
|
||||
# Project
|
||||
#*****************************************************************************************************************************************************
|
||||
|
||||
|
||||
project(bridge-gui-tester LANGUAGES CXX)
|
||||
|
||||
if (NOT DEFINED BRIDGE_APP_VERSION)
|
||||
message(FATAL_ERROR "BRIDGE_APP_VERSION is not defined.")
|
||||
else()
|
||||
message(STATUS "Bridge version is ${BRIDGE_APP_VERSION}")
|
||||
endif()
|
||||
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
|
||||
#*****************************************************************************************************************************************************
|
||||
# Qt
|
||||
#*****************************************************************************************************************************************************
|
||||
|
||||
|
||||
if (NOT DEFINED ENV{QT6DIR})
|
||||
message(FATAL_ERROR "QT6DIR needs to be defined and point to the root of your Qt 6 folder (e.g. /Users/MyName/Qt/6.3.1/clang_64).")
|
||||
endif()
|
||||
|
||||
set(CMAKE_PREFIX_PATH $ENV{QT6DIR} ${CMAKE_PREFIX_PATH})
|
||||
find_package(Qt6 COMPONENTS Core Gui Widgets Qml REQUIRED)
|
||||
qt_standard_project_setup()
|
||||
message(STATUS "Using Qt ${Qt6_VERSION}")
|
||||
|
||||
|
||||
#*****************************************************************************************************************************************************
|
||||
# Source files and output
|
||||
#*****************************************************************************************************************************************************
|
||||
|
||||
if (NOT TARGET bridgepp)
|
||||
add_subdirectory(../bridgepp bridgepp)
|
||||
endif()
|
||||
|
||||
add_executable(bridge-gui-tester
|
||||
AppController.cpp AppController.h
|
||||
main.cpp
|
||||
MainWindow.cpp MainWindow.h
|
||||
GRPCQtProxy.cpp GRPCQtProxy.h
|
||||
GRPCService.cpp GRPCService.h
|
||||
GRPCServerWorker.cpp GRPCServerWorker.h
|
||||
Tabs/SettingsTab.cpp Tabs/SettingsTab.h
|
||||
Tabs/UsersTab.cpp Tabs/UsersTab.h
|
||||
UserDialog.cpp UserDialog.h
|
||||
UserTable.cpp UserTable.h
|
||||
)
|
||||
|
||||
target_precompile_headers(bridge-gui-tester PRIVATE Pch.h)
|
||||
target_include_directories(bridge-gui-tester PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
target_compile_definitions(bridge-gui-tester PRIVATE BRIDGE_APP_VERSION=\"${BRIDGE_APP_VERSION}\")
|
||||
|
||||
|
||||
target_link_libraries(bridge-gui-tester
|
||||
Qt6::Core
|
||||
Qt6::Gui
|
||||
Qt6::Widgets
|
||||
Qt6::Qml
|
||||
bridgepp
|
||||
)
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,220 +0,0 @@
|
||||
// Copyright (c) 2022 Proton AG
|
||||
//
|
||||
// This file is part of Proton Mail Bridge.
|
||||
//
|
||||
// Proton Mail Bridge is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Proton Mail Bridge is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
#include "GRPCQtProxy.h"
|
||||
#include "MainWindow.h"
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
//
|
||||
//****************************************************************************************************************************************************
|
||||
GRPCQtProxy::GRPCQtProxy()
|
||||
: QObject(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
//
|
||||
//****************************************************************************************************************************************************
|
||||
void GRPCQtProxy::connectSignals()
|
||||
{
|
||||
MainWindow &mainWindow = app().mainWindow();
|
||||
SettingsTab &settingsTab = mainWindow.settingsTab();
|
||||
UsersTab &usersTab = mainWindow.usersTab();
|
||||
connect(this, &GRPCQtProxy::delayedEventRequested, &mainWindow, &MainWindow::sendDelayedEvent);
|
||||
connect(this, &GRPCQtProxy::setIsAutostartOnReceived, &settingsTab, &SettingsTab::setIsAutostartOn);
|
||||
connect(this, &GRPCQtProxy::setIsBetaEnabledReceived, &settingsTab, &SettingsTab::setIsBetaEnabled);
|
||||
connect(this, &GRPCQtProxy::setIsAllMailVisibleReceived, &settingsTab, &SettingsTab::setIsAllMailVisible);
|
||||
connect(this, &GRPCQtProxy::setColorSchemeNameReceived, &settingsTab, &SettingsTab::setColorSchemeName);
|
||||
connect(this, &GRPCQtProxy::reportBugReceived, &settingsTab, &SettingsTab::setBugReport);
|
||||
connect(this, &GRPCQtProxy::setIsStreamingReceived, &settingsTab, &SettingsTab::setIsStreaming);
|
||||
connect(this, &GRPCQtProxy::setClientPlatformReceived, &settingsTab, &SettingsTab::setClientPlatform);
|
||||
connect(this, &GRPCQtProxy::changePortsReceived, &settingsTab, &SettingsTab::changePorts);
|
||||
connect(this, &GRPCQtProxy::setUseSSLForSMTPReceived, &settingsTab, &SettingsTab::setUseSSLForSMTP);
|
||||
connect(this, &GRPCQtProxy::setIsDoHEnabledReceived, &settingsTab, &SettingsTab::setIsDoHEnabled);
|
||||
connect(this, &GRPCQtProxy::changeLocalCacheReceived, &settingsTab, &SettingsTab::changeLocalCache);
|
||||
connect(this, &GRPCQtProxy::setIsAutomaticUpdateOnReceived, &settingsTab, &SettingsTab::setIsAutomaticUpdateOn);
|
||||
connect(this, &GRPCQtProxy::setUserSplitModeReceived, &usersTab, &UsersTab::setUserSplitMode);
|
||||
connect(this, &GRPCQtProxy::removeUserReceived, &usersTab, &UsersTab::removeUser);
|
||||
connect(this, &GRPCQtProxy::logoutUserReceived, &usersTab, &UsersTab::logoutUser);
|
||||
connect(this, &GRPCQtProxy::setUserSplitModeReceived, &usersTab, &UsersTab::setUserSplitMode);
|
||||
connect(this, &GRPCQtProxy::configureUserAppleMailReceived, &usersTab, &UsersTab::configureUserAppleMail);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] event The event.
|
||||
//****************************************************************************************************************************************************
|
||||
void GRPCQtProxy::sendDelayedEvent(bridgepp::SPStreamEvent const &event)
|
||||
{
|
||||
emit delayedEventRequested(event);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] on The value.
|
||||
//****************************************************************************************************************************************************
|
||||
void GRPCQtProxy::setIsAutostartOn(bool on)
|
||||
{
|
||||
emit setIsAutostartOnReceived(on);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] enabled The value.
|
||||
//****************************************************************************************************************************************************
|
||||
void GRPCQtProxy::setIsBetaEnabled(bool enabled)
|
||||
{
|
||||
emit setIsBetaEnabledReceived(enabled);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] visible The value.
|
||||
//****************************************************************************************************************************************************
|
||||
void GRPCQtProxy::setIsAllMailVisible(bool visible)
|
||||
{
|
||||
emit setIsAllMailVisibleReceived(visible);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] name The color scheme.
|
||||
//****************************************************************************************************************************************************
|
||||
void GRPCQtProxy::setColorSchemeName(QString const &name)
|
||||
{
|
||||
emit setColorSchemeNameReceived(name);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] osType The OS type.
|
||||
/// \param[in] osVersion The OS version.
|
||||
/// \param[in] emailClient The email client.
|
||||
/// \param[in] address The address.
|
||||
/// \param[in] description The description.
|
||||
/// \param[in] includeLogs Should the logs be included.
|
||||
//****************************************************************************************************************************************************
|
||||
void GRPCQtProxy::reportBug(QString const &osType, QString const &osVersion, QString const &emailClient, QString const &address,
|
||||
QString const &description, bool includeLogs)
|
||||
{
|
||||
emit reportBugReceived(osType, osVersion, emailClient, address, description, includeLogs);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] isStreaming Is the gRPC server streaming.
|
||||
//****************************************************************************************************************************************************
|
||||
void GRPCQtProxy::setIsStreaming(bool isStreaming)
|
||||
{
|
||||
emit setIsStreamingReceived(isStreaming);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] clientPlatform The client platform.
|
||||
//****************************************************************************************************************************************************
|
||||
void GRPCQtProxy::setClientPlatform(QString const &clientPlatform)
|
||||
{
|
||||
emit setClientPlatformReceived(clientPlatform);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] imapPort The IMAP port
|
||||
/// \param[in] smtpPort The SMTP port
|
||||
//****************************************************************************************************************************************************
|
||||
void GRPCQtProxy::changePorts(qint32 imapPort, qint32 smtpPort)
|
||||
{
|
||||
emit changePortsReceived(imapPort, smtpPort);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] use Should SMTP use SSL?
|
||||
//****************************************************************************************************************************************************
|
||||
void GRPCQtProxy::setUseSSLForSMTP(bool use)
|
||||
{
|
||||
emit setUseSSLForSMTPReceived(use);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] enabled Is DoH enabled?
|
||||
//****************************************************************************************************************************************************
|
||||
void GRPCQtProxy::setIsDoHEnabled(bool enabled)
|
||||
{
|
||||
emit setIsDoHEnabledReceived(enabled);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] enabled is cache on disk enabled?
|
||||
/// \param[in] path The path for the cache on disk.
|
||||
//****************************************************************************************************************************************************
|
||||
void GRPCQtProxy::changeLocalCache(bool enabled, QString const &path)
|
||||
{
|
||||
emit changeLocalCacheReceived(enabled, path);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] on Is automatic update on?
|
||||
//****************************************************************************************************************************************************
|
||||
void GRPCQtProxy::setIsAutomaticUpdateOn(bool on)
|
||||
{
|
||||
emit setIsAutomaticUpdateOnReceived(on);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] userID The userID.
|
||||
/// \param[in] makeItActive Should split mode be active.
|
||||
//****************************************************************************************************************************************************
|
||||
void GRPCQtProxy::setUserSplitMode(QString const &userID, bool makeItActive)
|
||||
{
|
||||
emit setUserSplitModeReceived(userID, makeItActive);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] userID The userID.
|
||||
//****************************************************************************************************************************************************
|
||||
void GRPCQtProxy::logoutUser(QString const &userID)
|
||||
{
|
||||
emit logoutUserReceived(userID);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] userID The userID.
|
||||
//****************************************************************************************************************************************************
|
||||
void GRPCQtProxy::removeUser(QString const &userID)
|
||||
{
|
||||
emit removeUserReceived(userID);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] userID The userID.
|
||||
/// \param[in] address The address.
|
||||
//****************************************************************************************************************************************************
|
||||
void GRPCQtProxy::configureUserAppleMail(QString const &userID, QString const &address)
|
||||
{
|
||||
emit configureUserAppleMailReceived(userID, address);
|
||||
}
|
||||
@ -1,82 +0,0 @@
|
||||
// Copyright (c) 2022 Proton AG
|
||||
//
|
||||
// This file is part of Proton Mail Bridge.
|
||||
//
|
||||
// Proton Mail Bridge is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Proton Mail Bridge is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
#ifndef BRIDGE_GUI_TESTER_GRPC_QT_PROXY_H
|
||||
#define BRIDGE_GUI_TESTER_GRPC_QT_PROXY_H
|
||||
|
||||
|
||||
#include <bridgepp/GRPC/GRPCUtils.h>
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \brief Proxy object used by the gRPC service (which does not inherit QObject) to use the Qt Signal/Slot system.
|
||||
//****************************************************************************************************************************************************
|
||||
class GRPCQtProxy : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public: // member functions.
|
||||
GRPCQtProxy(); ///< Default constructor.
|
||||
GRPCQtProxy(GRPCQtProxy const &) = delete; ///< Disabled copy-constructor.
|
||||
GRPCQtProxy(GRPCQtProxy &&) = delete; ///< Disabled assignment copy-constructor.
|
||||
~GRPCQtProxy() override = default; ///< Destructor.
|
||||
GRPCQtProxy &operator=(GRPCQtProxy const &) = delete; ///< Disabled assignment operator.
|
||||
GRPCQtProxy &operator=(GRPCQtProxy &&) = delete; ///< Disabled move assignment operator.
|
||||
|
||||
void connectSignals(); // connect the signals to the main window.
|
||||
void sendDelayedEvent(bridgepp::SPStreamEvent const &event); ///< Sends a delayed stream event.
|
||||
void setIsAutostartOn(bool on); ///< Forwards a SetIsAutostartOn call via a Qt signal.
|
||||
void setIsBetaEnabled(bool enabled); ///< Forwards a SetIsBetaEnabled call via a Qt signal.
|
||||
void setIsAllMailVisible(bool visible); ///< Forwards a SetIsAllMailVisible call via a Qt signal.
|
||||
void setColorSchemeName(QString const &name); ///< Forward a SetColorSchemeName call via a Qt Signal
|
||||
void reportBug(QString const &osType, QString const &osVersion, QString const &emailClient, QString const &address,
|
||||
QString const &description, bool includeLogs); ///< Forwards a ReportBug call via a Qt signal.
|
||||
void setIsStreaming(bool isStreaming); ///< Forward a isStreaming internal messages via a Qt signal.
|
||||
void setClientPlatform(QString const &clientPlatform); ///< Forward s setClientPlatform call via a Qt signal.
|
||||
void changePorts(qint32 imapPort, qint32 smtpPort); ///< Forwards a ChangePorts call via a Qt signal.
|
||||
void setUseSSLForSMTP(bool use); ///< Forwards a SetUseSSLForSMTP call via a Qt signal.
|
||||
void setIsDoHEnabled(bool enabled); ///< Forwards a setIsDoHEnabled call via a Qt signal.
|
||||
void changeLocalCache(bool enabled, QString const &path); ///< Forwards a ChangeLocalPath call via a Qt signal.
|
||||
void setIsAutomaticUpdateOn(bool on); ///< Forwards a SetIsAutomaticUpdateOn call via a Qt signal.
|
||||
void setUserSplitMode(QString const &userID, bool makeItActive); ///< Forwards a setUserSplitMode call via a Qt signal.
|
||||
void logoutUser(QString const &userID); ///< Forwards a logoutUser call via a Qt signal.
|
||||
void removeUser(QString const &userID); ///< Forwards a removeUser call via a Qt signal.
|
||||
void configureUserAppleMail(QString const &userID, QString const &address); ///< Forwards a configureUserAppleMail call via a Qt signal.
|
||||
|
||||
signals:
|
||||
void delayedEventRequested(bridgepp::SPStreamEvent const &event); ///< Signal for sending a delayed event. delayed is set in the UI.
|
||||
void setIsAutostartOnReceived(bool on); ///< Forwards a SetIsAutostartOn call via a Qt signal.
|
||||
void setIsBetaEnabledReceived(bool enabled); ///< Forwards a SetIsBetaEnabled call via a Qt signal.
|
||||
void setIsAllMailVisibleReceived(bool enabled); ///< Forwards a SetIsBetaEnabled call via a Qt signal.
|
||||
void setColorSchemeNameReceived(QString const &name); ///< Forward a SetColorScheme call via a Qt Signal
|
||||
void reportBugReceived(QString const &osType, QString const &osVersion, QString const &emailClient, QString const &address,
|
||||
QString const &description, bool includeLogs); ///< Signal for the ReportBug gRPC call
|
||||
void setIsStreamingReceived(bool isStreaming); ///< Signal for the IsStreaming internal message.
|
||||
void setClientPlatformReceived(QString const &clientPlatform); ///< Signal for the SetClientPlatform gRPC call.
|
||||
void changePortsReceived(qint32 imapPort, qint32 smtpPort); ///< Signal for the ChangePorts gRPC call.
|
||||
void setUseSSLForSMTPReceived(bool use); ///< Signal for the SetUseSSLForSMTP gRPC call.
|
||||
void setIsDoHEnabledReceived(bool enabled); ///< Signal for the SetIsDoHEnabled gRPC call.
|
||||
void changeLocalCacheReceived(bool enabled, QString const &path); ///< Signal for the ChangeLocalPath gRPC call.
|
||||
void setIsAutomaticUpdateOnReceived(bool on); ///< Signal for the SetIsAutomaticUpdateOn gRPC call.
|
||||
void setUserSplitModeReceived(QString const &userID, bool makeItActive); ///< Signal for the SetUserSplitModeReceived gRPC call.
|
||||
void logoutUserReceived(QString const &userID); ///< Signal for the LogoutUserReceived gRPC call.
|
||||
void removeUserReceived(QString const &userID); ///< Signal for the RemoveUserReceived gRPC call.
|
||||
void configureUserAppleMailReceived(QString const &userID, QString const &address); ///< Signal for the ConfigureAppleMail gRPC call.
|
||||
};
|
||||
|
||||
|
||||
#endif //BRIDGE_GUI_TESTER_GRPC_QT_PROXY_H
|
||||
@ -1,109 +0,0 @@
|
||||
// Copyright (c) 2022 Proton AG
|
||||
//
|
||||
// This file is part of Proton Mail Bridge.
|
||||
//
|
||||
// Proton Mail Bridge is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Proton Mail Bridge is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
#include "GRPCServerWorker.h"
|
||||
#include "GRPCService.h"
|
||||
#include <bridgepp/Exception/Exception.h>
|
||||
#include <bridgepp/GRPC/GRPCUtils.h>
|
||||
|
||||
|
||||
using namespace bridgepp;
|
||||
using namespace grpc;
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return The content of the file.
|
||||
//****************************************************************************************************************************************************
|
||||
QString loadAsciiTextFile(QString const &path) {
|
||||
QFile file(path);
|
||||
return file.open(QIODevice::ReadOnly | QIODevice::Text) ? QString::fromLocal8Bit(file.readAll()) : QString();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
//
|
||||
//****************************************************************************************************************************************************
|
||||
GRPCServerWorker::GRPCServerWorker(QObject *parent)
|
||||
: Worker(parent)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
//
|
||||
//****************************************************************************************************************************************************
|
||||
void GRPCServerWorker::run()
|
||||
{
|
||||
try
|
||||
{
|
||||
emit started();
|
||||
|
||||
QString cert = loadAsciiTextFile(serverCertificatePath());
|
||||
if (cert.isEmpty())
|
||||
throw Exception("Could not locate server certificate. Make sure to launch bridge once before starting this application");
|
||||
|
||||
QString key = loadAsciiTextFile(serverKeyPath());
|
||||
if (key.isEmpty())
|
||||
throw Exception("Could not locate server key. Make sure to launch bridge once before starting this application");
|
||||
|
||||
SslServerCredentialsOptions::PemKeyCertPair pair;
|
||||
pair.private_key = key.toStdString();
|
||||
pair.cert_chain = cert.toStdString();
|
||||
SslServerCredentialsOptions ssl_opts;
|
||||
ssl_opts.pem_root_certs="";
|
||||
ssl_opts.pem_key_cert_pairs.push_back(pair);
|
||||
std::shared_ptr<ServerCredentials> credentials = grpc::SslServerCredentials(ssl_opts);
|
||||
|
||||
ServerBuilder builder;
|
||||
builder.AddListeningPort("127.0.0.1:9292", credentials);
|
||||
builder.RegisterService(&app().grpc());
|
||||
server_ = builder.BuildAndStart();
|
||||
if (!server_)
|
||||
throw Exception("Could not create gRPC server.");
|
||||
app().log().debug("gRPC Server started.");
|
||||
|
||||
server_->Wait();
|
||||
emit finished();
|
||||
app().log().debug("gRPC Server exited.");
|
||||
}
|
||||
catch (Exception const &e)
|
||||
{
|
||||
if (server_)
|
||||
server_->Shutdown();
|
||||
|
||||
emit error(e.qwhat());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
//
|
||||
//****************************************************************************************************************************************************
|
||||
void GRPCServerWorker::stop()
|
||||
{
|
||||
if (server_)
|
||||
server_->Shutdown();
|
||||
}
|
||||
@ -1,50 +0,0 @@
|
||||
// Copyright (c) 2022 Proton AG
|
||||
//
|
||||
// This file is part of Proton Mail Bridge.
|
||||
//
|
||||
// Proton Mail Bridge is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Proton Mail Bridge is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
#ifndef BRIDGE_GUI_TESTER_SERVER_WORKER_H
|
||||
#define BRIDGE_GUI_TESTER_SERVER_WORKER_H
|
||||
|
||||
|
||||
#include <bridgepp/Worker/Worker.h>
|
||||
#include "GRPCService.h"
|
||||
#include <grpcpp/grpcpp.h>
|
||||
|
||||
|
||||
//**********************************************************************************************************************
|
||||
/// \brief gRPC server worker
|
||||
//**********************************************************************************************************************
|
||||
class GRPCServerWorker : public bridgepp::Worker
|
||||
{
|
||||
Q_OBJECT
|
||||
public: // member functions.
|
||||
explicit GRPCServerWorker(QObject *parent); ///< Default constructor.
|
||||
GRPCServerWorker(GRPCServerWorker const &) = delete; ///< Disabled copy-constructor.
|
||||
GRPCServerWorker(GRPCServerWorker &&) = delete; ///< Disabled assignment copy-constructor.
|
||||
~GRPCServerWorker() override = default; ///< Destructor.
|
||||
GRPCServerWorker &operator=(GRPCServerWorker const &) = delete; ///< Disabled assignment operator.
|
||||
GRPCServerWorker &operator=(GRPCServerWorker &&) = delete; ///< Disabled move assignment operator.
|
||||
|
||||
void run() override; ///< Run the worker.
|
||||
void stop(); ///< Stop the gRPC service.
|
||||
|
||||
private: // data members
|
||||
std::unique_ptr<grpc::Server> server_ { nullptr }; ///< The gRPC server.
|
||||
};
|
||||
|
||||
|
||||
#endif // BRIDGE_GUI_TESTER_SERVER_WORKER_H
|
||||
@ -1,916 +0,0 @@
|
||||
// Copyright (c) 2022 Proton AG
|
||||
//
|
||||
// This file is part of Proton Mail Bridge.
|
||||
//
|
||||
// Proton Mail Bridge is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Proton Mail Bridge is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
#include "GRPCService.h"
|
||||
#include "MainWindow.h"
|
||||
#include <bridgepp/BridgeUtils.h>
|
||||
#include <bridgepp/GRPC/EventFactory.h>
|
||||
|
||||
|
||||
using namespace grpc;
|
||||
using namespace google::protobuf;
|
||||
using namespace bridgepp;
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
|
||||
QString const defaultKeychain = "defaultKeychain"; ///< The default keychain.
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
//
|
||||
//****************************************************************************************************************************************************
|
||||
void GRPCService::connectProxySignals()
|
||||
{
|
||||
qtProxy_.connectSignals();
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return true iff the service is streaming events.
|
||||
//****************************************************************************************************************************************************
|
||||
bool GRPCService::isStreaming() const
|
||||
{
|
||||
QMutexLocker locker(&eventStreamMutex_);
|
||||
return isStreaming_;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] request the request.
|
||||
/// \return The status for the call.
|
||||
//****************************************************************************************************************************************************
|
||||
Status GRPCService::AddLogEntry(ServerContext *, AddLogEntryRequest const *request, Empty *)
|
||||
{
|
||||
app().bridgeGUILog().addEntry(logLevelFromGRPC(request->level()), QString::fromStdString(request->message()));
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return The status for the call.
|
||||
//****************************************************************************************************************************************************
|
||||
Status GRPCService::GuiReady(ServerContext *, Empty const *, Empty *)
|
||||
{
|
||||
app().log().debug(__FUNCTION__);
|
||||
app().mainWindow().settingsTab().setGUIReady(true);
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return The status for the call.
|
||||
//****************************************************************************************************************************************************
|
||||
Status GRPCService::Quit(ServerContext *, Empty const *, Empty *)
|
||||
{
|
||||
// We do not actually quit.
|
||||
app().log().debug(__FUNCTION__);
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return The status for the call.
|
||||
//****************************************************************************************************************************************************
|
||||
Status GRPCService::Restart(ServerContext *, Empty const *, Empty *)
|
||||
{
|
||||
// we do not actually restart.
|
||||
app().log().debug(__FUNCTION__);
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[out] response The response.
|
||||
/// \return The status for the call.
|
||||
//****************************************************************************************************************************************************
|
||||
Status GRPCService::ShowOnStartup(ServerContext *, Empty const *, BoolValue *response)
|
||||
{
|
||||
app().log().debug(__FUNCTION__);
|
||||
response->set_value(app().mainWindow().settingsTab().showOnStartup());
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[out] response The response.
|
||||
/// \return The status for the call.
|
||||
//****************************************************************************************************************************************************
|
||||
Status GRPCService::ShowSplashScreen(ServerContext *, Empty const *, BoolValue *response)
|
||||
{
|
||||
app().log().debug(__FUNCTION__);
|
||||
response->set_value(app().mainWindow().settingsTab().showSplashScreen());
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[out] response The response.
|
||||
/// \return The status for the call.
|
||||
//****************************************************************************************************************************************************
|
||||
Status GRPCService::IsFirstGuiStart(ServerContext *, Empty const *, BoolValue *response)
|
||||
{
|
||||
app().log().debug(__FUNCTION__);
|
||||
response->set_value(app().mainWindow().settingsTab().isFirstGUIStart());
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] request The request.
|
||||
/// \return The status for the call.
|
||||
//****************************************************************************************************************************************************
|
||||
Status GRPCService::SetIsAutostartOn(ServerContext *, BoolValue const *request, Empty *)
|
||||
{
|
||||
app().log().debug(__FUNCTION__);
|
||||
app().mainWindow().settingsTab().setIsAutostartOn(request->value());
|
||||
qtProxy_.sendDelayedEvent(newToggleAutostartFinishedEvent());
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[out] response The response.
|
||||
/// \return The status for the call.
|
||||
//****************************************************************************************************************************************************
|
||||
Status GRPCService::IsAutostartOn(ServerContext *, Empty const *, BoolValue *response)
|
||||
{
|
||||
app().log().debug(__FUNCTION__);
|
||||
response->set_value(app().mainWindow().settingsTab().isAutostartOn());
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] request The request.
|
||||
/// \return The status for the call.
|
||||
//****************************************************************************************************************************************************
|
||||
Status GRPCService::SetIsBetaEnabled(ServerContext *, BoolValue const *request, Empty *)
|
||||
{
|
||||
app().log().debug(__FUNCTION__);
|
||||
qtProxy_.setIsBetaEnabled(request->value());
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[out] response The response.
|
||||
/// \return The status for the call.
|
||||
//****************************************************************************************************************************************************
|
||||
Status GRPCService::IsBetaEnabled(ServerContext *, Empty const *, BoolValue *response)
|
||||
{
|
||||
app().log().debug(__FUNCTION__);
|
||||
response->set_value(app().mainWindow().settingsTab().isBetaEnabled());
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] request The request.
|
||||
/// \return The status for the call.
|
||||
//****************************************************************************************************************************************************
|
||||
Status GRPCService::SetIsAllMailVisible(ServerContext *, BoolValue const *request, Empty *)
|
||||
{
|
||||
app().log().debug(__FUNCTION__);
|
||||
qtProxy_.setIsAllMailVisible(request->value());
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[out] response The response.
|
||||
/// \return The status for the call.
|
||||
//****************************************************************************************************************************************************
|
||||
Status GRPCService::IsAllMailVisible(ServerContext *, Empty const *request, BoolValue *response)
|
||||
{
|
||||
app().log().debug(__FUNCTION__);
|
||||
response->set_value(app().mainWindow().settingsTab().isAllMailVisible());
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[out] response The response.
|
||||
/// \return The status for the call.
|
||||
//****************************************************************************************************************************************************
|
||||
Status GRPCService::GoOs(ServerContext *, Empty const *, StringValue *response)
|
||||
{
|
||||
app().log().debug(__FUNCTION__);
|
||||
response->set_value(app().mainWindow().settingsTab().os().toStdString());
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return The status for the call.
|
||||
//****************************************************************************************************************************************************
|
||||
Status GRPCService::TriggerReset(ServerContext *, Empty const *, Empty *)
|
||||
{
|
||||
app().log().debug(__FUNCTION__);
|
||||
app().log().info("Bridge GUI requested a reset");
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[out] response The response.
|
||||
/// \return The status for the call.
|
||||
//****************************************************************************************************************************************************
|
||||
grpc::Status GRPCService::Version(ServerContext *, Empty const *, StringValue *response)
|
||||
{
|
||||
app().log().debug(__FUNCTION__);
|
||||
response->set_value(app().mainWindow().settingsTab().bridgeVersion().toStdString());
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[out] response The response.
|
||||
/// \return The status for the call.
|
||||
//****************************************************************************************************************************************************
|
||||
Status GRPCService::LogsPath(ServerContext *, Empty const *, StringValue *response)
|
||||
{
|
||||
app().log().debug(__FUNCTION__);
|
||||
response->set_value(app().mainWindow().settingsTab().logsPath().toStdString());
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[out] response The response.
|
||||
/// \return The status for the call.
|
||||
//****************************************************************************************************************************************************
|
||||
Status GRPCService::LicensePath(ServerContext *, Empty const *, StringValue *response)
|
||||
{
|
||||
app().log().debug(__FUNCTION__);
|
||||
response->set_value(app().mainWindow().settingsTab().licensePath().toStdString());
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[out] response The response.
|
||||
/// \return The status for the call.
|
||||
//****************************************************************************************************************************************************
|
||||
Status GRPCService::ReleaseNotesPageLink(ServerContext *, Empty const *, StringValue *response)
|
||||
{
|
||||
app().log().debug(__FUNCTION__);
|
||||
response->set_value(app().mainWindow().settingsTab().releaseNotesPageLink().toStdString());
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[out] response The response.
|
||||
/// \return The status for the call.
|
||||
//****************************************************************************************************************************************************
|
||||
Status GRPCService::DependencyLicensesLink(ServerContext *, Empty const *, StringValue *response)
|
||||
{
|
||||
app().log().debug(__FUNCTION__);
|
||||
response->set_value(app().mainWindow().settingsTab().dependencyLicenseLink().toStdString());
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[out] response The response.
|
||||
/// \return The status for the call.
|
||||
//****************************************************************************************************************************************************
|
||||
Status GRPCService::LandingPageLink(ServerContext *, Empty const *, StringValue *response)
|
||||
{
|
||||
app().log().debug(__FUNCTION__);
|
||||
response->set_value(app().mainWindow().settingsTab().landingPageLink().toStdString());
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] request The request.
|
||||
/// \return The status for the call.
|
||||
//****************************************************************************************************************************************************
|
||||
Status GRPCService::SetColorSchemeName(ServerContext *, StringValue const *request, Empty *)
|
||||
{
|
||||
app().log().debug(__FUNCTION__);
|
||||
qtProxy_.setColorSchemeName(QString::fromStdString(request->value()));
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] response The response.
|
||||
/// \return The status for the call.
|
||||
//****************************************************************************************************************************************************
|
||||
Status GRPCService::ColorSchemeName(ServerContext *, Empty const *, StringValue *response)
|
||||
{
|
||||
app().log().debug(__FUNCTION__);
|
||||
response->set_value(app().mainWindow().settingsTab().colorSchemeName().toStdString());
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] response The response.
|
||||
/// \return The status for the call.
|
||||
//****************************************************************************************************************************************************
|
||||
Status GRPCService::CurrentEmailClient(ServerContext *, Empty const *, StringValue *response)
|
||||
{
|
||||
app().log().debug(__FUNCTION__);
|
||||
response->set_value(app().mainWindow().settingsTab().currentEmailClient().toStdString());
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] request The request.
|
||||
/// \return The status for the call.
|
||||
//****************************************************************************************************************************************************
|
||||
Status GRPCService::ForceLauncher(ServerContext *, StringValue const *request, Empty *)
|
||||
{
|
||||
app().log().debug(__FUNCTION__);
|
||||
app().log().info(QString("ForceLauncher: %1").arg(QString::fromStdString(request->value())));
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] request The request.
|
||||
/// \return The status for the call.
|
||||
//****************************************************************************************************************************************************
|
||||
Status GRPCService::SetMainExecutable(ServerContext *, StringValue const *request, Empty *)
|
||||
{
|
||||
app().log().debug(__FUNCTION__);
|
||||
app().log().info(QString("SetMainExecutable: %1").arg(QString::fromStdString(request->value())));
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] request The request
|
||||
//****************************************************************************************************************************************************
|
||||
Status GRPCService::ReportBug(ServerContext *, ReportBugRequest const *request, Empty *)
|
||||
{
|
||||
app().log().debug(__FUNCTION__);
|
||||
SettingsTab &tab = app().mainWindow().settingsTab();
|
||||
qtProxy_.reportBug(QString::fromStdString(request->ostype()), QString::fromStdString(request->osversion()),
|
||||
QString::fromStdString(request->emailclient()), QString::fromStdString(request->address()), QString::fromStdString(request->description()),
|
||||
request->includelogs());
|
||||
qtProxy_.sendDelayedEvent(tab.nextBugReportWillSucceed() ? newReportBugSuccessEvent() : newReportBugErrorEvent());
|
||||
qtProxy_.sendDelayedEvent(newReportBugFinishedEvent());
|
||||
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] request The request.
|
||||
/// \return The status for the call.
|
||||
//****************************************************************************************************************************************************
|
||||
Status GRPCService::Login(ServerContext *, LoginRequest const *request, Empty *)
|
||||
{
|
||||
app().log().debug(__FUNCTION__);
|
||||
UsersTab &usersTab = app().mainWindow().usersTab();
|
||||
loginUsername_ = QString::fromStdString(request->username());
|
||||
if (usersTab.nextUserUsernamePasswordError())
|
||||
{
|
||||
qtProxy_.sendDelayedEvent(newLoginError(LoginErrorType::USERNAME_PASSWORD_ERROR, usersTab.usernamePasswordErrorMessage()));
|
||||
return Status::OK;
|
||||
}
|
||||
if (usersTab.nextUserFreeUserError())
|
||||
{
|
||||
qtProxy_.sendDelayedEvent(newLoginError(LoginErrorType::FREE_USER, "Free user error."));
|
||||
return Status::OK;
|
||||
}
|
||||
if (usersTab.nextUserTFARequired())
|
||||
{
|
||||
qtProxy_.sendDelayedEvent(newLoginTfaRequestedEvent(loginUsername_));
|
||||
return Status::OK;
|
||||
}
|
||||
if (usersTab.nextUserTwoPasswordsRequired())
|
||||
{
|
||||
qtProxy_.sendDelayedEvent(newLoginTwoPasswordsRequestedEvent());
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
SPUser const user = randomUser();
|
||||
QString const userID = user->id();
|
||||
user->setUsername(QString::fromStdString(request->username()));
|
||||
usersTab.userTable().append(user);
|
||||
|
||||
if (usersTab.nextUserAlreadyLoggedIn())
|
||||
qtProxy_.sendDelayedEvent(newLoginAlreadyLoggedInEvent(userID));
|
||||
qtProxy_.sendDelayedEvent(newLoginFinishedEvent(userID));
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] request The request.
|
||||
/// \return The status for the call.
|
||||
//****************************************************************************************************************************************************
|
||||
Status GRPCService::Login2FA(ServerContext *, LoginRequest const *request, Empty *)
|
||||
{
|
||||
app().log().debug(__FUNCTION__);
|
||||
UsersTab &usersTab = app().mainWindow().usersTab();
|
||||
if (usersTab.nextUserTFAError())
|
||||
{
|
||||
qtProxy_.sendDelayedEvent(newLoginError(LoginErrorType::TFA_ERROR, "2FA Error."));
|
||||
return Status::OK;
|
||||
}
|
||||
if (usersTab.nextUserTFAAbort())
|
||||
{
|
||||
qtProxy_.sendDelayedEvent(newLoginError(LoginErrorType::TFA_ABORT, "2FA Abort."));
|
||||
return Status::OK;
|
||||
}
|
||||
if (usersTab.nextUserTwoPasswordsRequired())
|
||||
{
|
||||
qtProxy_.sendDelayedEvent(newLoginTwoPasswordsRequestedEvent());
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
SPUser const user = randomUser();
|
||||
QString const userID = user->id();
|
||||
user->setUsername(QString::fromStdString(request->username()));
|
||||
usersTab.userTable().append(user);
|
||||
|
||||
if (usersTab.nextUserAlreadyLoggedIn())
|
||||
qtProxy_.sendDelayedEvent(newLoginAlreadyLoggedInEvent(userID));
|
||||
qtProxy_.sendDelayedEvent(newLoginFinishedEvent(userID));
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] request The request.
|
||||
/// \return The status for the call.
|
||||
//****************************************************************************************************************************************************
|
||||
Status GRPCService::Login2Passwords(ServerContext *, LoginRequest const *request, Empty *)
|
||||
{
|
||||
app().log().debug(__FUNCTION__);
|
||||
UsersTab &usersTab = app().mainWindow().usersTab();
|
||||
|
||||
if (usersTab.nextUserTwoPasswordsError())
|
||||
{
|
||||
qtProxy_.sendDelayedEvent(newLoginError(LoginErrorType::TWO_PASSWORDS_ERROR, "Two Passwords error."));
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
if (usersTab.nextUserTwoPasswordsAbort())
|
||||
{
|
||||
qtProxy_.sendDelayedEvent(newLoginError(LoginErrorType::TWO_PASSWORDS_ABORT, "Two Passwords abort."));
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
SPUser const user = randomUser();
|
||||
QString const userID = user->id();
|
||||
user->setUsername(QString::fromStdString(request->username()));
|
||||
usersTab.userTable().append(user);
|
||||
|
||||
if (usersTab.nextUserAlreadyLoggedIn())
|
||||
qtProxy_.sendDelayedEvent(newLoginAlreadyLoggedInEvent(userID));
|
||||
qtProxy_.sendDelayedEvent(newLoginFinishedEvent(userID));
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] request The request.
|
||||
/// \return The status for the call.
|
||||
//****************************************************************************************************************************************************
|
||||
Status GRPCService::LoginAbort(ServerContext *, LoginAbortRequest const *request, Empty *)
|
||||
{
|
||||
app().log().debug(__FUNCTION__);
|
||||
loginUsername_ = QString();
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return The status for the call.
|
||||
//****************************************************************************************************************************************************
|
||||
Status GRPCService::CheckUpdate(ServerContext *, Empty const *, Empty *)
|
||||
{
|
||||
/// \todo simulate update availability.
|
||||
app().log().debug(__FUNCTION__);
|
||||
app().log().info("Check for updates");
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return The status for the call.
|
||||
//****************************************************************************************************************************************************
|
||||
Status GRPCService::InstallUpdate(ServerContext *, Empty const *, Empty *)
|
||||
{
|
||||
/// Simulate update availability.
|
||||
app().log().debug(__FUNCTION__);
|
||||
app().log().info("Install update");
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] request The request.
|
||||
/// \return The status for the call.
|
||||
//****************************************************************************************************************************************************
|
||||
Status GRPCService::SetIsAutomaticUpdateOn(ServerContext *, BoolValue const *request, Empty *)
|
||||
{
|
||||
app().log().debug(__FUNCTION__);
|
||||
qtProxy_.setIsAutomaticUpdateOn(request->value());
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[out] response The response.
|
||||
/// \return The status for the call.
|
||||
//****************************************************************************************************************************************************
|
||||
Status GRPCService::IsAutomaticUpdateOn(ServerContext *, Empty const *, BoolValue *response)
|
||||
{
|
||||
app().log().debug(__FUNCTION__);
|
||||
response->set_value(app().mainWindow().settingsTab().isAutomaticUpdateOn());
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] response The response.
|
||||
/// \return The status for the call
|
||||
//****************************************************************************************************************************************************
|
||||
Status GRPCService::IsCacheOnDiskEnabled(ServerContext *, Empty const *, BoolValue *response)
|
||||
{
|
||||
app().log().debug(__FUNCTION__);
|
||||
response->set_value(app().mainWindow().settingsTab().isCacheOnDiskEnabled());
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] response The response.
|
||||
/// \return The status for the call
|
||||
//****************************************************************************************************************************************************
|
||||
Status GRPCService::DiskCachePath(ServerContext *, Empty const *, StringValue *response)
|
||||
{
|
||||
app().log().debug(__FUNCTION__);
|
||||
response->set_value(app().mainWindow().settingsTab().diskCachePath().toStdString());
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] request The request.
|
||||
/// \return The status for the call.
|
||||
//****************************************************************************************************************************************************
|
||||
Status GRPCService::ChangeLocalCache(ServerContext *, ChangeLocalCacheRequest const *request, Empty *)
|
||||
{
|
||||
app().log().debug(__FUNCTION__);
|
||||
SettingsTab &tab = app().mainWindow().settingsTab();
|
||||
QString const path = QString::fromStdString(request->diskcachepath());
|
||||
|
||||
// we mimic the behaviour of Bridge
|
||||
if (!tab.nextCacheChangeWillSucceed())
|
||||
qtProxy_.sendDelayedEvent(newCacheErrorEvent(grpc::CacheErrorType(tab.cacheError())));
|
||||
else
|
||||
qtProxy_.sendDelayedEvent(newCacheLocationChangeSuccessEvent());
|
||||
qtProxy_.sendDelayedEvent(newDiskCachePathChanged(path));
|
||||
qtProxy_.sendDelayedEvent(newIsCacheOnDiskEnabledChanged(request->enablediskcache()));
|
||||
qtProxy_.sendDelayedEvent(newChangeLocalCacheFinishedEvent());
|
||||
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] request The request.
|
||||
/// \return The status for the call.
|
||||
//****************************************************************************************************************************************************
|
||||
Status GRPCService::SetIsDoHEnabled(ServerContext *, BoolValue const *request, Empty *)
|
||||
{
|
||||
app().log().debug(__FUNCTION__);
|
||||
qtProxy_.setIsDoHEnabled(request->value());
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[out] response The response
|
||||
/// \return The status for the call.
|
||||
//****************************************************************************************************************************************************
|
||||
Status GRPCService::IsDoHEnabled(ServerContext *, Empty const *, BoolValue *response)
|
||||
{
|
||||
app().log().debug(__FUNCTION__);
|
||||
response->set_value(app().mainWindow().settingsTab().isDoHEnabled());
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] request The request.
|
||||
/// \return The status for the call.
|
||||
//****************************************************************************************************************************************************
|
||||
Status GRPCService::SetUseSslForSmtp(ServerContext *, BoolValue const *request, Empty *)
|
||||
{
|
||||
app().log().debug(__FUNCTION__);
|
||||
qtProxy_.setUseSSLForSMTP(request->value());
|
||||
qtProxy_.sendDelayedEvent(newUseSslForSmtpFinishedEvent());
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[out] response The response.
|
||||
/// \return The status for the call.
|
||||
//****************************************************************************************************************************************************
|
||||
Status GRPCService::UseSslForSmtp(ServerContext *, Empty const *, BoolValue *response)
|
||||
{
|
||||
app().log().debug(__FUNCTION__);
|
||||
response->set_value(app().mainWindow().settingsTab().useSSLForSMTP());
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[out] response The response.
|
||||
/// \return The status for the call.
|
||||
//****************************************************************************************************************************************************
|
||||
Status GRPCService::Hostname(ServerContext *, Empty const *, StringValue *response)
|
||||
{
|
||||
app().log().debug(__FUNCTION__);
|
||||
response->set_value(app().mainWindow().settingsTab().hostname().toStdString());
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[out] response The response.
|
||||
/// \return The status for the call.
|
||||
//****************************************************************************************************************************************************
|
||||
Status GRPCService::ImapPort(ServerContext *, Empty const *, Int32Value *response)
|
||||
{
|
||||
app().log().debug(__FUNCTION__);
|
||||
response->set_value(app().mainWindow().settingsTab().imapPort());
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[out] response The response.
|
||||
/// \return The status for the call.
|
||||
//****************************************************************************************************************************************************
|
||||
Status GRPCService::SmtpPort(ServerContext *, Empty const *, Int32Value *response)
|
||||
{
|
||||
app().log().debug(__FUNCTION__);
|
||||
response->set_value(app().mainWindow().settingsTab().smtpPort());
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] request The request.
|
||||
/// \return The status for the call.
|
||||
//****************************************************************************************************************************************************
|
||||
Status GRPCService::ChangePorts(ServerContext *, ChangePortsRequest const *request, Empty *)
|
||||
{
|
||||
app().log().debug(__FUNCTION__);
|
||||
qtProxy_.changePorts(request->imapport(), request->smtpport());
|
||||
qtProxy_.sendDelayedEvent(newChangePortsFinishedEvent());
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] request The request.
|
||||
/// \param[out] response The response.
|
||||
/// \return The status for the call.
|
||||
//****************************************************************************************************************************************************
|
||||
Status GRPCService::IsPortFree(ServerContext *, Int32Value const *request, BoolValue *response)
|
||||
{
|
||||
app().log().debug(__FUNCTION__);
|
||||
response->set_value(app().mainWindow().settingsTab().isPortFree());
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[out] response The response.
|
||||
/// \return The status for the call
|
||||
//****************************************************************************************************************************************************
|
||||
Status GRPCService::AvailableKeychains(ServerContext *, Empty const *, AvailableKeychainsResponse *response)
|
||||
{
|
||||
/// \todo Implement keychains configuration.
|
||||
app().log().debug(__FUNCTION__);
|
||||
response->clear_keychains();
|
||||
response->add_keychains(defaultKeychain.toStdString());
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] request The request.
|
||||
/// \return The status for the call
|
||||
//****************************************************************************************************************************************************
|
||||
Status GRPCService::SetCurrentKeychain(ServerContext *, StringValue const *request, Empty *)
|
||||
{
|
||||
/// \todo Implement keychains configuration.
|
||||
app().log().debug(__FUNCTION__);
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[out] response The response.
|
||||
/// \return The status for the call
|
||||
//****************************************************************************************************************************************************
|
||||
Status GRPCService::CurrentKeychain(ServerContext *, Empty const *, StringValue *response)
|
||||
{
|
||||
/// \todo Implement keychains configuration.
|
||||
app().log().debug(__FUNCTION__);
|
||||
response->set_value(defaultKeychain.toStdString());
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[out] response The response.
|
||||
/// \return The status for the call
|
||||
//****************************************************************************************************************************************************
|
||||
Status GRPCService::GetUserList(ServerContext *, Empty const *, UserListResponse *response)
|
||||
{
|
||||
app().log().debug(__FUNCTION__);
|
||||
response->clear_users();
|
||||
|
||||
QList<SPUser> userList = app().mainWindow().usersTab().userTable().users();
|
||||
RepeatedPtrField<grpc::User> *users = response->mutable_users();
|
||||
for (SPUser const &user: userList)
|
||||
{
|
||||
if (!user)
|
||||
continue;
|
||||
users->Add();
|
||||
grpc::User &grpcUser = (*users)[users->size() - 1];
|
||||
userToGRPC(*user, grpcUser);
|
||||
}
|
||||
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] request The request.
|
||||
/// \param[out] response The response.
|
||||
/// \return The status for the call.
|
||||
//****************************************************************************************************************************************************
|
||||
Status GRPCService::GetUser(ServerContext *, StringValue const *request, grpc::User *response)
|
||||
{
|
||||
app().log().debug(__FUNCTION__);
|
||||
QString userID = QString::fromStdString(request->value());
|
||||
SPUser user = app().mainWindow().usersTab().userWithID(userID);
|
||||
if (!user)
|
||||
return Status(NOT_FOUND, QString("user not found %1").arg(userID).toStdString());
|
||||
|
||||
userToGRPC(*user, *response);
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] request The request.
|
||||
/// \return The status for the call.
|
||||
//****************************************************************************************************************************************************
|
||||
Status GRPCService::SetUserSplitMode(ServerContext *, UserSplitModeRequest const *request, Empty *)
|
||||
{
|
||||
app().log().debug(__FUNCTION__);
|
||||
qtProxy_.setUserSplitMode(QString::fromStdString(request->userid()), request->active());
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] request The request.
|
||||
/// \return The status for the call.
|
||||
//****************************************************************************************************************************************************
|
||||
Status GRPCService::LogoutUser(ServerContext *, StringValue const *request, Empty *)
|
||||
{
|
||||
app().log().debug(__FUNCTION__);
|
||||
qtProxy_.logoutUser(QString::fromStdString(request->value()));
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] request The request.
|
||||
/// \return The status for the call.
|
||||
//****************************************************************************************************************************************************
|
||||
Status GRPCService::RemoveUser(ServerContext *, StringValue const *request, Empty *)
|
||||
{
|
||||
app().log().debug(__FUNCTION__);
|
||||
qtProxy_.removeUser(QString::fromStdString(request->value()));
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] request The request.
|
||||
//****************************************************************************************************************************************************
|
||||
Status GRPCService::ConfigureUserAppleMail(ServerContext *, ConfigureAppleMailRequest const *request, Empty *)
|
||||
{
|
||||
app().log().debug(__FUNCTION__);
|
||||
qtProxy_.configureUserAppleMail(QString::fromStdString(request->userid()), QString::fromStdString(request->address()));
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] request The request
|
||||
/// \param[in] writer The writer
|
||||
/// \return The status for the call.
|
||||
//****************************************************************************************************************************************************
|
||||
Status GRPCService::RunEventStream(ServerContext *, EventStreamRequest const *request, ServerWriter<StreamEvent> *writer)
|
||||
{
|
||||
app().log().debug(__FUNCTION__);
|
||||
{
|
||||
QMutexLocker locker(&eventStreamMutex_);
|
||||
if (isStreaming_)
|
||||
return { grpc::ALREADY_EXISTS, "the service is already streaming" };
|
||||
isStreaming_ = true;
|
||||
qtProxy_.setIsStreaming(true);
|
||||
qtProxy_.setClientPlatform(QString::fromStdString(request->clientplatform()));
|
||||
eventStreamShouldStop_ = false;
|
||||
}
|
||||
|
||||
while (true)
|
||||
{
|
||||
QMutexLocker locker(&eventStreamMutex_);
|
||||
if (eventStreamShouldStop_)
|
||||
{
|
||||
qtProxy_.setIsStreaming(false);
|
||||
qtProxy_.setClientPlatform(QString());
|
||||
isStreaming_ = false;
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
|
||||
if (eventQueue_.isEmpty())
|
||||
{
|
||||
locker.unlock();
|
||||
QThread::msleep(100);
|
||||
continue;
|
||||
}
|
||||
SPStreamEvent const event = eventQueue_.front();
|
||||
eventQueue_.pop_front();
|
||||
locker.unlock();
|
||||
|
||||
if (writer->Write(*event))
|
||||
app().log().debug(QString("event sent: %1").arg(QString::fromStdString(event->ShortDebugString())));
|
||||
else
|
||||
app().log().error(QString("Could not send event: %1").arg(QString::fromStdString(event->ShortDebugString())));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return The status for the call.
|
||||
//****************************************************************************************************************************************************
|
||||
Status GRPCService::StopEventStream(ServerContext *, Empty const *, Empty *)
|
||||
{
|
||||
app().log().debug(__FUNCTION__);
|
||||
QMutexLocker mutex(&eventStreamMutex_);
|
||||
if (!isStreaming_)
|
||||
return Status(NOT_FOUND, "The service is not streaming");
|
||||
eventStreamShouldStop_ = true;
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] event The event
|
||||
/// \return true if the event was queued, and false if the server in not streaming.
|
||||
//****************************************************************************************************************************************************
|
||||
bool GRPCService::sendEvent(SPStreamEvent const &event)
|
||||
{
|
||||
QMutexLocker mutexLocker(&eventStreamMutex_);
|
||||
if (isStreaming_)
|
||||
eventQueue_.push_back(event);
|
||||
return isStreaming_;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@ -1,115 +0,0 @@
|
||||
// Copyright (c) 2022 Proton AG
|
||||
//
|
||||
// This file is part of Proton Mail Bridge.
|
||||
//
|
||||
// Proton Mail Bridge is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Proton Mail Bridge is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
#ifndef BRIDGE_GUI_TESTER_GRPC_SERVER_H
|
||||
#define BRIDGE_GUI_TESTER_GRPC_SERVER_H
|
||||
|
||||
|
||||
#include "GRPCQtProxy.h"
|
||||
#include <bridgepp/GRPC/bridge.grpc.pb.h>
|
||||
#include <bridgepp/GRPC/GRPCUtils.h>
|
||||
|
||||
|
||||
//**********************************************************************************************************************
|
||||
/// \brief gRPC server implementation.
|
||||
//**********************************************************************************************************************
|
||||
class GRPCService : public grpc::Bridge::Service
|
||||
{
|
||||
|
||||
public: // member functions.
|
||||
GRPCService() = default; ///< Default constructor.
|
||||
GRPCService(GRPCService const &) = delete; ///< Disabled copy-constructor.
|
||||
GRPCService(GRPCService &&) = delete; ///< Disabled assignment copy-constructor.
|
||||
~GRPCService() override = default; ///< Destructor.
|
||||
GRPCService &operator=(GRPCService const &) = delete; ///< Disabled assignment operator.
|
||||
GRPCService &operator=(GRPCService &&) = delete; ///< Disabled move assignment operator.
|
||||
void connectProxySignals(); ///< Connect the signals of the Qt Proxy to the GUI components
|
||||
bool isStreaming() const; ///< Check if the service is currently streaming events.
|
||||
|
||||
grpc::Status AddLogEntry(::grpc::ServerContext *, ::grpc::AddLogEntryRequest const *request, ::google::protobuf::Empty *) override;
|
||||
grpc::Status GuiReady(::grpc::ServerContext *, ::google::protobuf::Empty const*, ::google::protobuf::Empty *) override;
|
||||
grpc::Status Quit(::grpc::ServerContext *, ::google::protobuf::Empty const*, ::google::protobuf::Empty *) override;
|
||||
grpc::Status Restart(::grpc::ServerContext *, ::google::protobuf::Empty const*, ::google::protobuf::Empty *) override;
|
||||
grpc::Status ShowOnStartup(::grpc::ServerContext *, ::google::protobuf::Empty const*, ::google::protobuf::BoolValue *response) override;
|
||||
grpc::Status ShowSplashScreen(::grpc::ServerContext *, ::google::protobuf::Empty const*, ::google::protobuf::BoolValue *response) override;
|
||||
grpc::Status IsFirstGuiStart(::grpc::ServerContext *, ::google::protobuf::Empty const*, ::google::protobuf::BoolValue *response) override;
|
||||
grpc::Status SetIsAutostartOn(::grpc::ServerContext *, ::google::protobuf::BoolValue const *request, ::google::protobuf::Empty *) override;
|
||||
grpc::Status IsAutostartOn(::grpc::ServerContext *, ::google::protobuf::Empty const*, ::google::protobuf::BoolValue *response) override;
|
||||
grpc::Status SetIsBetaEnabled(::grpc::ServerContext *, ::google::protobuf::BoolValue const *request, ::google::protobuf::Empty *) override;
|
||||
grpc::Status IsBetaEnabled(::grpc::ServerContext *, ::google::protobuf::Empty const*, ::google::protobuf::BoolValue *response) override;
|
||||
grpc::Status SetIsAllMailVisible(::grpc::ServerContext *context, ::google::protobuf::BoolValue const *request, ::google::protobuf::Empty *response) override;
|
||||
grpc::Status IsAllMailVisible(::grpc::ServerContext *context, ::google::protobuf::Empty const *request, ::google::protobuf::BoolValue *response) override;
|
||||
grpc::Status GoOs(::grpc::ServerContext *, ::google::protobuf::Empty const*, ::google::protobuf::StringValue *response) override;
|
||||
grpc::Status TriggerReset(::grpc::ServerContext *, ::google::protobuf::Empty const*, ::google::protobuf::Empty *) override;
|
||||
grpc::Status Version(::grpc::ServerContext *, ::google::protobuf::Empty const*, ::google::protobuf::StringValue *response) override;
|
||||
grpc::Status LogsPath(::grpc::ServerContext *, ::google::protobuf::Empty const*, ::google::protobuf::StringValue *response) override;
|
||||
grpc::Status LicensePath(::grpc::ServerContext *, ::google::protobuf::Empty const*, ::google::protobuf::StringValue *response) override;
|
||||
grpc::Status ReleaseNotesPageLink(::grpc::ServerContext *, ::google::protobuf::Empty const*, ::google::protobuf::StringValue *response) override;
|
||||
grpc::Status DependencyLicensesLink(::grpc::ServerContext *, ::google::protobuf::Empty const*, ::google::protobuf::StringValue *response) override;
|
||||
grpc::Status LandingPageLink(::grpc::ServerContext *, ::google::protobuf::Empty const*, ::google::protobuf::StringValue *response) override;
|
||||
grpc::Status SetColorSchemeName(::grpc::ServerContext *, ::google::protobuf::StringValue const *request, ::google::protobuf::Empty *) override;
|
||||
grpc::Status ColorSchemeName(::grpc::ServerContext *, ::google::protobuf::Empty const*, ::google::protobuf::StringValue *response) override;
|
||||
grpc::Status CurrentEmailClient(::grpc::ServerContext *, ::google::protobuf::Empty const*, ::google::protobuf::StringValue *response) override;
|
||||
grpc::Status ReportBug(::grpc::ServerContext *, ::grpc::ReportBugRequest const *request, ::google::protobuf::Empty *) override;
|
||||
grpc::Status ForceLauncher(::grpc::ServerContext *, ::google::protobuf::StringValue const *request, ::google::protobuf::Empty *) override;
|
||||
grpc::Status SetMainExecutable(::grpc::ServerContext *, ::google::protobuf::StringValue const *request, ::google::protobuf::Empty *) override;
|
||||
grpc::Status Login(::grpc::ServerContext *, ::grpc::LoginRequest const *request, ::google::protobuf::Empty *) override;
|
||||
grpc::Status Login2FA(::grpc::ServerContext *, ::grpc::LoginRequest const *request, ::google::protobuf::Empty *) override;
|
||||
grpc::Status Login2Passwords(::grpc::ServerContext *, ::grpc::LoginRequest const *request, ::google::protobuf::Empty *) override;
|
||||
grpc::Status LoginAbort(::grpc::ServerContext *, ::grpc::LoginAbortRequest const *request, ::google::protobuf::Empty *) override;
|
||||
grpc::Status CheckUpdate(::grpc::ServerContext *, ::google::protobuf::Empty const*, ::google::protobuf::Empty *) override;
|
||||
grpc::Status InstallUpdate(::grpc::ServerContext *, ::google::protobuf::Empty const*, ::google::protobuf::Empty *) override;
|
||||
grpc::Status SetIsAutomaticUpdateOn(::grpc::ServerContext *, ::google::protobuf::BoolValue const *request, ::google::protobuf::Empty *) override;
|
||||
grpc::Status IsAutomaticUpdateOn(::grpc::ServerContext *, ::google::protobuf::Empty const*, ::google::protobuf::BoolValue *response) override;
|
||||
grpc::Status IsCacheOnDiskEnabled(::grpc::ServerContext *, ::google::protobuf::Empty const*, ::google::protobuf::BoolValue *response) override;
|
||||
grpc::Status DiskCachePath(::grpc::ServerContext *, ::google::protobuf::Empty const*, ::google::protobuf::StringValue *response) override;
|
||||
grpc::Status ChangeLocalCache(::grpc::ServerContext *, ::grpc::ChangeLocalCacheRequest const *request, ::google::protobuf::Empty *) override;
|
||||
grpc::Status SetIsDoHEnabled(::grpc::ServerContext *, ::google::protobuf::BoolValue const *request, ::google::protobuf::Empty *) override;
|
||||
grpc::Status IsDoHEnabled(::grpc::ServerContext *, ::google::protobuf::Empty const*, ::google::protobuf::BoolValue *response) override;
|
||||
grpc::Status SetUseSslForSmtp(::grpc::ServerContext *, ::google::protobuf::BoolValue const *request, ::google::protobuf::Empty *) override;
|
||||
grpc::Status UseSslForSmtp(::grpc::ServerContext *, ::google::protobuf::Empty const*, ::google::protobuf::BoolValue *response) override;
|
||||
grpc::Status Hostname(::grpc::ServerContext *, ::google::protobuf::Empty const*, ::google::protobuf::StringValue *response) override;
|
||||
grpc::Status ImapPort(::grpc::ServerContext *, ::google::protobuf::Empty const*, ::google::protobuf::Int32Value *response) override;
|
||||
grpc::Status SmtpPort(::grpc::ServerContext *, ::google::protobuf::Empty const*, ::google::protobuf::Int32Value *response) override;
|
||||
grpc::Status ChangePorts(::grpc::ServerContext *, ::grpc::ChangePortsRequest const *request, ::google::protobuf::Empty *) override;
|
||||
grpc::Status IsPortFree(::grpc::ServerContext *, ::google::protobuf::Int32Value const *request, ::google::protobuf::BoolValue *response) override;
|
||||
grpc::Status AvailableKeychains(::grpc::ServerContext *, ::google::protobuf::Empty const*, ::grpc::AvailableKeychainsResponse *response) override;
|
||||
grpc::Status SetCurrentKeychain(::grpc::ServerContext *, ::google::protobuf::StringValue const *request, ::google::protobuf::Empty *) override;
|
||||
grpc::Status CurrentKeychain(::grpc::ServerContext *, ::google::protobuf::Empty const*, ::google::protobuf::StringValue *response) override;
|
||||
grpc::Status GetUserList(::grpc::ServerContext *, ::google::protobuf::Empty const*, ::grpc::UserListResponse *response) override;
|
||||
grpc::Status GetUser(::grpc::ServerContext *, ::google::protobuf::StringValue const *request, ::grpc::User *response) override;
|
||||
grpc::Status SetUserSplitMode(::grpc::ServerContext *, ::grpc::UserSplitModeRequest const *request, ::google::protobuf::Empty *) override;
|
||||
grpc::Status LogoutUser(::grpc::ServerContext *, ::google::protobuf::StringValue const *request, ::google::protobuf::Empty *) override;
|
||||
grpc::Status RemoveUser(::grpc::ServerContext *, ::google::protobuf::StringValue const *request, ::google::protobuf::Empty *) override;
|
||||
grpc::Status ConfigureUserAppleMail(::grpc::ServerContext *, ::grpc::ConfigureAppleMailRequest const *request, ::google::protobuf::Empty *) override;
|
||||
grpc::Status RunEventStream(::grpc::ServerContext *, ::grpc::EventStreamRequest const *request, ::grpc::ServerWriter<::grpc::StreamEvent> *writer) override;
|
||||
grpc::Status StopEventStream(::grpc::ServerContext *, ::google::protobuf::Empty const*, ::google::protobuf::Empty *) override;
|
||||
|
||||
bool sendEvent(bridgepp::SPStreamEvent const &event); ///< Queue an event for sending through the event stream.
|
||||
|
||||
private: // data member
|
||||
mutable QMutex eventStreamMutex_; ///< Mutex used to access eventQueue_, isStreaming_ and shouldStopStreaming_;
|
||||
QList<bridgepp::SPStreamEvent> eventQueue_; ///< The event queue. Acces protected by eventStreamMutex_;
|
||||
bool isStreaming_; ///< Is the gRPC stream running. Access protected by eventStreamMutex_;
|
||||
bool eventStreamShouldStop_; ///< Should the stream be stopped? Access protected by eventStreamMutex
|
||||
QString loginUsername_; ///< The username used for the current login procedure.
|
||||
GRPCQtProxy qtProxy_; ///< Qt Proxy used to send signals, as this class is not a QObject.
|
||||
};
|
||||
|
||||
|
||||
#endif // BRIDGE_GUI_TESTER_GRPC_SERVER_H
|
||||
@ -1,111 +0,0 @@
|
||||
// Copyright (c) 2022 Proton AG
|
||||
//
|
||||
// This file is part of Proton Mail Bridge.
|
||||
//
|
||||
// Proton Mail Bridge is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Proton Mail Bridge is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
#include "MainWindow.h"
|
||||
#include <bridgepp/Log/Log.h>
|
||||
|
||||
|
||||
using namespace bridgepp;
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] level The log level.
|
||||
/// \param[in] message The log message.
|
||||
/// \param[in] logEdit The plain text edit widget that displays the log.
|
||||
//****************************************************************************************************************************************************
|
||||
void addEntryToLogEdit(bridgepp::Log::Level level, const QString &message, QPlainTextEdit &logEdit)
|
||||
{
|
||||
/// \todo This may cause performance issue when log grows big. A better alternative should be implemented.
|
||||
QString log = logEdit.toPlainText().trimmed();
|
||||
if (!log.isEmpty())
|
||||
log += "\n";
|
||||
logEdit.setPlainText(log + Log::logEntryToString(level, message));
|
||||
}
|
||||
|
||||
|
||||
} // Anonymous namespace
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] parent The parent widget of the window.
|
||||
//****************************************************************************************************************************************************
|
||||
MainWindow::MainWindow(QWidget *parent)
|
||||
: QMainWindow(parent)
|
||||
{
|
||||
ui_.setupUi(this);
|
||||
ui_.tabTop->setCurrentIndex(0);
|
||||
ui_.tabBottom->setCurrentIndex(0);
|
||||
ui_.splitter->setStretchFactor(0, 0);
|
||||
ui_.splitter->setStretchFactor(1, 1);
|
||||
ui_.splitter->setSizes({100, 10000});
|
||||
connect(&app().log(), &Log::entryAdded, this, &MainWindow::addLogEntry);
|
||||
connect(&app().bridgeGUILog(), &Log::entryAdded, this, &MainWindow::addBridgeGUILogEntry);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return A reference to the 'General' tab.
|
||||
//****************************************************************************************************************************************************
|
||||
SettingsTab &MainWindow::settingsTab()
|
||||
{
|
||||
return *ui_.settingsTab;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return A reference to the users tab.
|
||||
//****************************************************************************************************************************************************
|
||||
UsersTab &MainWindow::usersTab()
|
||||
{
|
||||
return *ui_.usersTab;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] level The log level.
|
||||
/// \param[in] message The log message
|
||||
//****************************************************************************************************************************************************
|
||||
void MainWindow::addLogEntry(bridgepp::Log::Level level, const QString &message)
|
||||
{
|
||||
addEntryToLogEdit(level, message, *ui_.editLog);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] level The log level.
|
||||
/// \param[in] message The log message
|
||||
//****************************************************************************************************************************************************
|
||||
void MainWindow::addBridgeGUILogEntry(bridgepp::Log::Level level, const QString &message)
|
||||
{
|
||||
addEntryToLogEdit(level, message, *ui_.editBridgeGUILog);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] event The event.
|
||||
//****************************************************************************************************************************************************
|
||||
void MainWindow::sendDelayedEvent(SPStreamEvent const &event)
|
||||
{
|
||||
QTimer::singleShot(this->settingsTab().eventDelayMs(), [event] { app().grpc().sendEvent(event); });
|
||||
}
|
||||
|
||||
|
||||
@ -1,57 +0,0 @@
|
||||
// Copyright (c) 2022 Proton AG
|
||||
//
|
||||
// This file is part of Proton Mail Bridge.
|
||||
//
|
||||
// Proton Mail Bridge is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Proton Mail Bridge is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
#ifndef BRIDGE_GUI_TESTER_MAIN_WINDOW_H
|
||||
#define BRIDGE_GUI_TESTER_MAIN_WINDOW_H
|
||||
|
||||
|
||||
#include "ui_MainWindow.h"
|
||||
#include "GRPCService.h"
|
||||
#include <bridgepp/Log/Log.h>
|
||||
|
||||
|
||||
//**********************************************************************************************************************
|
||||
/// \brief Main window class
|
||||
//**********************************************************************************************************************
|
||||
class MainWindow : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
public: // member functions.
|
||||
explicit MainWindow(QWidget *parent); ///< Default constructor.
|
||||
MainWindow(MainWindow const &) = delete; ///< Disabled copy-constructor.
|
||||
MainWindow(MainWindow &&) = delete; ///< Disabled assignment copy-constructor.
|
||||
~MainWindow() override = default; ///< Destructor.
|
||||
MainWindow &operator=(MainWindow const &) = delete; ///< Disabled assignment operator.
|
||||
MainWindow &operator=(MainWindow &&) = delete; ///< Disabled move assignment operator.
|
||||
|
||||
SettingsTab &settingsTab(); ///< Returns a reference the 'Settings' tab.
|
||||
UsersTab &usersTab(); ///< Returns a reference to the 'Users' tab.
|
||||
|
||||
public slots:
|
||||
void sendDelayedEvent(bridgepp::SPStreamEvent const& event); ///< Sends a gRPC event after the delay specified in the UI. The call is non blocking.
|
||||
|
||||
private slots:
|
||||
void addLogEntry(bridgepp::Log::Level level, QString const &message); ///< Add an entry to the log.
|
||||
void addBridgeGUILogEntry(bridgepp::Log::Level level, const QString &message); ///< Add an entry to the log.
|
||||
|
||||
private:
|
||||
Ui::MainWindow ui_ {}; ///< The GUI for the window.
|
||||
};
|
||||
|
||||
|
||||
#endif // BRIDGE_GUI_TESTER_MAIN_WINDOW_H
|
||||
@ -1,102 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>MainWindow</class>
|
||||
<widget class="QMainWindow" name="MainWindow">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1226</width>
|
||||
<height>1086</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>MainWindow</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralWidget">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QSplitter" name="splitter">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<widget class="QTabWidget" name="tabTop">
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="SettingsTab" name="settingsTab">
|
||||
<attribute name="title">
|
||||
<string>Settings</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
<widget class="UsersTab" name="usersTab">
|
||||
<attribute name="title">
|
||||
<string>Users</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
</widget>
|
||||
<widget class="QTabWidget" name="tabBottom">
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="tabLog">
|
||||
<attribute name="title">
|
||||
<string>Log</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QPlainTextEdit" name="editLog">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Monaco</family>
|
||||
</font>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tabBridgeGUILog">
|
||||
<attribute name="title">
|
||||
<string>Bridge-GUI Log</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<widget class="QPlainTextEdit" name="editBridgeGUILog">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Monaco</family>
|
||||
</font>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>SettingsTab</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>Tabs/SettingsTab.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>UsersTab</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>Tabs/UsersTab.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@ -1,29 +0,0 @@
|
||||
// Copyright (c) 2022 Proton AG
|
||||
//
|
||||
// This file is part of Proton Mail Bridge.
|
||||
//
|
||||
// Proton Mail Bridge is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Proton Mail Bridge is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
#ifndef BRIDGE_GUI_PCH_H
|
||||
#define BRIDGE_GUI_PCH_H
|
||||
|
||||
|
||||
#include <QtCore>
|
||||
#include <QtGui>
|
||||
#include <QtWidgets>
|
||||
#include "AppController.h"
|
||||
|
||||
|
||||
#endif // BRIDGE_GUI_PCH_H
|
||||
@ -1,516 +0,0 @@
|
||||
// Copyright (c) 2022 Proton AG
|
||||
//
|
||||
// This file is part of Proton Mail Bridge.
|
||||
//
|
||||
// Proton Mail Bridge is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Proton Mail Bridge is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
#include "SettingsTab.h"
|
||||
#include "GRPCService.h"
|
||||
#include <bridgepp/GRPC/EventFactory.h>
|
||||
#include <bridgepp/BridgeUtils.h>
|
||||
|
||||
|
||||
using namespace bridgepp;
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
QString const colorSchemeDark = "dark"; ///< The dark color scheme name.
|
||||
QString const colorSchemeLight = "light"; ///< THe light color scheme name.
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] parent The parent widget of the tab.
|
||||
//****************************************************************************************************************************************************
|
||||
SettingsTab::SettingsTab(QWidget *parent)
|
||||
: QWidget(parent)
|
||||
{
|
||||
ui_.setupUi(this);
|
||||
|
||||
connect(ui_.buttonInternetOn, &QPushButton::clicked, []() { app().grpc().sendEvent(newInternetStatusEvent(true)); });
|
||||
connect(ui_.buttonInternetOff, &QPushButton::clicked, []() { app().grpc().sendEvent(newInternetStatusEvent(false)); });
|
||||
connect(ui_.buttonShowMainWindow, &QPushButton::clicked, []() { app().grpc().sendEvent(newShowMainWindowEvent()); });
|
||||
connect(ui_.checkNextCacheChangeWillSucceed, &QCheckBox::toggled, this, &SettingsTab::updateGUIState);
|
||||
this->resetUI();
|
||||
this->updateGUIState();
|
||||
}
|
||||
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
//
|
||||
//****************************************************************************************************************************************************
|
||||
void SettingsTab::updateGUIState()
|
||||
{
|
||||
bool connected = app().grpc().isStreaming();
|
||||
for (QWidget *widget: { ui_.groupVersion, ui_.groupGeneral, ui_.groupMail, ui_.groupPaths, ui_.groupCache })
|
||||
widget->setEnabled(!connected);
|
||||
ui_.comboCacheError -> setEnabled(!ui_.checkNextCacheChangeWillSucceed->isChecked());
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] isStreaming Is the event stream on?
|
||||
//****************************************************************************************************************************************************
|
||||
void SettingsTab::setIsStreaming(bool isStreaming)
|
||||
{
|
||||
ui_.labelStreamingValue->setText(isStreaming ? "Yes" : "No");
|
||||
this->updateGUIState();
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] clientPlatform The client platform.
|
||||
//****************************************************************************************************************************************************
|
||||
void SettingsTab::setClientPlatform(QString const &clientPlatform)
|
||||
{
|
||||
ui_.labelClientPlatformValue->setText(clientPlatform);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return The version of Bridge
|
||||
//****************************************************************************************************************************************************
|
||||
QString SettingsTab::bridgeVersion() const
|
||||
{
|
||||
return ui_.editVersion->text();
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return The OS as a Go GOOS compatible value ("darwin", "linux" or "windows").
|
||||
//****************************************************************************************************************************************************
|
||||
QString SettingsTab::os() const
|
||||
{
|
||||
return ui_.comboOS->currentText();
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return The value for the 'Current Email Client' edit.
|
||||
//****************************************************************************************************************************************************
|
||||
QString SettingsTab::currentEmailClient() const
|
||||
{
|
||||
return ui_.editCurrentEmailClient->text();
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] ready Is the GUI ready?
|
||||
//****************************************************************************************************************************************************
|
||||
void SettingsTab::setGUIReady(bool ready)
|
||||
{
|
||||
this->updateGUIState();
|
||||
ui_.labelGUIReadyValue->setText(ready ? "Yes" : "No");
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return true iff the 'Show On Startup' check box is checked.
|
||||
//****************************************************************************************************************************************************
|
||||
bool SettingsTab::showOnStartup() const
|
||||
{
|
||||
return ui_.checkShowOnStartup->isChecked();
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return true iff the 'Show Splash Screen' check box is checked.
|
||||
//****************************************************************************************************************************************************
|
||||
bool SettingsTab::showSplashScreen() const
|
||||
{
|
||||
return ui_.checkShowSplashScreen->isChecked();
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return true iff the 'Show Splash Screen' check box is checked.
|
||||
//****************************************************************************************************************************************************
|
||||
bool SettingsTab::isFirstGUIStart() const
|
||||
{
|
||||
return ui_.checkIsFirstGUIStart->isChecked();
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return true iff autosart is on.
|
||||
//****************************************************************************************************************************************************
|
||||
bool SettingsTab::isAutostartOn() const
|
||||
{
|
||||
return ui_.checkAutostart->isChecked();
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] on Should autostart be turned on?
|
||||
//****************************************************************************************************************************************************
|
||||
void SettingsTab::setIsAutostartOn(bool on)
|
||||
{
|
||||
ui_.checkAutostart->setChecked(on);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return true if the 'Use Dark Theme' check box is checked.
|
||||
//****************************************************************************************************************************************************
|
||||
QString SettingsTab::colorSchemeName() const
|
||||
{
|
||||
return ui_.checkDarkTheme->isChecked() ? colorSchemeDark : colorSchemeLight;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] name True if the 'Use Dark Theme' check box should be checked.
|
||||
//****************************************************************************************************************************************************
|
||||
void SettingsTab::setColorSchemeName(QString const &name)
|
||||
{
|
||||
ui_.checkDarkTheme->setChecked(name == colorSchemeDark);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return true if the 'Beta Enabled' check box is checked.
|
||||
//****************************************************************************************************************************************************
|
||||
bool SettingsTab::isBetaEnabled() const
|
||||
{
|
||||
return ui_.checkBetaEnabled->isChecked();
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] enabled The new state for the 'Beta Enabled' check box.
|
||||
//****************************************************************************************************************************************************
|
||||
void SettingsTab::setIsBetaEnabled(bool enabled)
|
||||
{
|
||||
ui_.checkBetaEnabled->setChecked(enabled);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return true if the 'All Mail Visible' check box is checked.
|
||||
//****************************************************************************************************************************************************
|
||||
bool SettingsTab::isAllMailVisible() const
|
||||
{
|
||||
return ui_.checkAllMailVisible->isChecked();
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] visible The new value for the 'All Mail Visible' check box.
|
||||
//****************************************************************************************************************************************************
|
||||
void SettingsTab::setIsAllMailVisible(bool visible)
|
||||
{
|
||||
ui_.checkAllMailVisible->setChecked(visible);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return The delay to apply before sending automatically generated events.
|
||||
//****************************************************************************************************************************************************
|
||||
qint32 SettingsTab::eventDelayMs() const
|
||||
{
|
||||
return ui_.spinEventDelay->value();
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return The path
|
||||
//****************************************************************************************************************************************************
|
||||
QString SettingsTab::logsPath() const
|
||||
{
|
||||
return ui_.editLogsPath->text();
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return The path
|
||||
//****************************************************************************************************************************************************
|
||||
QString SettingsTab::licensePath() const
|
||||
{
|
||||
return ui_.editLicensePath->text();
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return The link.
|
||||
//****************************************************************************************************************************************************
|
||||
QString SettingsTab::releaseNotesPageLink() const
|
||||
{
|
||||
return ui_.editReleaseNotesLink->text();
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return The link.
|
||||
//****************************************************************************************************************************************************
|
||||
QString SettingsTab::dependencyLicenseLink() const
|
||||
{
|
||||
return ui_.editDependencyLicenseLink->text();
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return The link.
|
||||
//****************************************************************************************************************************************************
|
||||
QString SettingsTab::landingPageLink() const
|
||||
{
|
||||
return ui_.editLandingPageLink->text();
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] osType The OS type.
|
||||
/// \param[in] osVersion The OS version.
|
||||
/// \param[in] emailClient The email client.
|
||||
/// \param[in] address The email address.
|
||||
/// \param[in] description The description.
|
||||
/// \param[in] includeLogs Are the log included.
|
||||
//****************************************************************************************************************************************************
|
||||
void SettingsTab::setBugReport(QString const &osType, QString const &osVersion, QString const &emailClient, QString const &address,
|
||||
QString const &description, bool includeLogs)
|
||||
{
|
||||
ui_.editOSType->setText(osType);
|
||||
ui_.editOSVersion->setText(osVersion);
|
||||
ui_.editEmailClient->setText(emailClient);
|
||||
ui_.editAddress->setText(address);
|
||||
ui_.editDescription->setPlainText(description);
|
||||
ui_.labelIncludeLogsValue->setText(includeLogs ? "Yes" : "No");
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return The state of the check box.
|
||||
//****************************************************************************************************************************************************
|
||||
bool SettingsTab::nextBugReportWillSucceed() const
|
||||
{
|
||||
return ui_.checkNextBugReportWillSucceed->isChecked();
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return The value of the 'Hostname' edit.
|
||||
//****************************************************************************************************************************************************
|
||||
QString SettingsTab::hostname() const
|
||||
{
|
||||
return ui_.editHostname->text();
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return The value of the IMAP port spin box.
|
||||
//****************************************************************************************************************************************************
|
||||
qint32 SettingsTab::imapPort()
|
||||
{
|
||||
return ui_.spinPortIMAP->value();
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return The value of the SMTP port spin box.
|
||||
//****************************************************************************************************************************************************
|
||||
qint32 SettingsTab::smtpPort()
|
||||
{
|
||||
return ui_.spinPortSMTP->value();
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] imapPort The IMAP port.
|
||||
/// \param[in] smtpPort The SMTP port.
|
||||
//****************************************************************************************************************************************************
|
||||
void SettingsTab::changePorts(qint32 imapPort, qint32 smtpPort)
|
||||
{
|
||||
ui_.spinPortIMAP->setValue(imapPort);
|
||||
ui_.spinPortSMTP->setValue(smtpPort);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return The state of the 'Use SSL for SMTP' check box.
|
||||
//****************************************************************************************************************************************************
|
||||
bool SettingsTab::useSSLForSMTP() const
|
||||
{
|
||||
return ui_.checkUseSSLForSMTP->isChecked();
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] use The state of the 'Use SSL for SMTP' check box.
|
||||
//****************************************************************************************************************************************************
|
||||
void SettingsTab::setUseSSLForSMTP(bool use)
|
||||
{
|
||||
ui_.checkUseSSLForSMTP->setChecked(use);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return The state of the the 'DoH enabled' check box.
|
||||
//****************************************************************************************************************************************************
|
||||
bool SettingsTab::isDoHEnabled() const
|
||||
{
|
||||
return ui_.checkDoHEnabled->isChecked();
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] enabled The state of the 'DoH enabled' check box.
|
||||
//****************************************************************************************************************************************************
|
||||
void SettingsTab::setIsDoHEnabled(bool enabled)
|
||||
{
|
||||
ui_.checkDoHEnabled->setChecked(enabled);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return The reply for the next IsPortFree gRPC call.
|
||||
//****************************************************************************************************************************************************
|
||||
bool SettingsTab::isPortFree() const
|
||||
{
|
||||
return ui_.checkIsPortFree->isChecked();
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return true iff cache on disk is enabled.
|
||||
//****************************************************************************************************************************************************
|
||||
bool SettingsTab::isCacheOnDiskEnabled() const
|
||||
{
|
||||
return ui_.checkCacheOnDiskEnabled->isChecked();
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] enabled Is the cache on disk enabled?
|
||||
/// \param[in] path The path of the local cache.
|
||||
//****************************************************************************************************************************************************
|
||||
void SettingsTab::changeLocalCache(bool enabled, QString const &path)
|
||||
{
|
||||
ui_.checkCacheOnDiskEnabled->setChecked(enabled);
|
||||
ui_.editDiskCachePath->setText(path);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return The disk cache path.
|
||||
//****************************************************************************************************************************************************
|
||||
QString SettingsTab::diskCachePath() const
|
||||
{
|
||||
return ui_.editDiskCachePath->text();
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return The value for the 'Next Cache Change Will Succeed' check box.
|
||||
//****************************************************************************************************************************************************
|
||||
bool SettingsTab::nextCacheChangeWillSucceed() const
|
||||
{
|
||||
return ui_.checkNextCacheChangeWillSucceed->isChecked();
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return The index of the selected cache error.
|
||||
//****************************************************************************************************************************************************
|
||||
qint32 SettingsTab::cacheError() const
|
||||
{
|
||||
return ui_.comboCacheError->currentIndex();
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return the value for the 'Automatic Update' check.
|
||||
//****************************************************************************************************************************************************
|
||||
bool SettingsTab::isAutomaticUpdateOn() const
|
||||
{
|
||||
return ui_.checkAutomaticUpdate->isChecked();
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] on The value for the 'Automatic Update' check.
|
||||
//****************************************************************************************************************************************************
|
||||
void SettingsTab::setIsAutomaticUpdateOn(bool on)
|
||||
{
|
||||
ui_.checkAutomaticUpdate->setChecked(on);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
//
|
||||
//****************************************************************************************************************************************************
|
||||
void SettingsTab::resetUI()
|
||||
{
|
||||
this->setGUIReady(false);
|
||||
this->setIsStreaming(false);
|
||||
this->setClientPlatform("Unknown");
|
||||
|
||||
ui_.editVersion->setText(BRIDGE_APP_VERSION);
|
||||
ui_.comboOS->setCurrentText(bridgepp::goos());
|
||||
ui_.editCurrentEmailClient->setText("Thunderbird/102.0.3");
|
||||
ui_.checkShowOnStartup->setChecked(true);
|
||||
ui_.checkShowSplashScreen->setChecked(false);
|
||||
ui_.checkIsFirstGUIStart->setChecked(false);
|
||||
ui_.checkAutostart->setChecked(true);
|
||||
ui_.checkBetaEnabled->setChecked(true);
|
||||
ui_.checkAllMailVisible->setChecked(true);
|
||||
ui_.checkDarkTheme->setChecked(false);
|
||||
|
||||
QString const tmpDir = QStandardPaths::writableLocation(QStandardPaths::TempLocation);
|
||||
|
||||
QString const logsDir = QDir(tmpDir).absoluteFilePath("logs");
|
||||
QDir().mkpath(logsDir);
|
||||
ui_.editLogsPath->setText(QDir::toNativeSeparators(logsDir));
|
||||
|
||||
QString const filePath = QDir(tmpDir).absoluteFilePath("LICENSE.txt");
|
||||
QFile file(filePath);
|
||||
if (!file.exists())
|
||||
{
|
||||
// we don't really care if it fails.
|
||||
file.open(QIODevice::WriteOnly | QIODevice::Text);
|
||||
file.write(QString("This is were the license should be.").toLocal8Bit());
|
||||
file.close();
|
||||
}
|
||||
ui_.editLicensePath->setText(filePath);
|
||||
|
||||
ui_.editReleaseNotesLink->setText("https://en.wikipedia.org/wiki/Release_notes");
|
||||
ui_.editDependencyLicenseLink->setText("https://en.wikipedia.org/wiki/Dependency_relation");
|
||||
ui_.editLandingPageLink->setText("https://proton.me");
|
||||
|
||||
ui_.editOSType->setText(QString());
|
||||
ui_.editOSVersion->setText(QString());
|
||||
ui_.editEmailClient->setText(QString());
|
||||
ui_.editAddress->setText(QString());
|
||||
ui_.editDescription->setPlainText(QString());
|
||||
ui_.labelIncludeLogsValue->setText(QString());
|
||||
ui_.checkNextBugReportWillSucceed->setChecked(true);
|
||||
|
||||
ui_.editHostname->setText("localhost");
|
||||
ui_.spinPortIMAP->setValue(1143);
|
||||
ui_.spinPortSMTP->setValue(1025);
|
||||
ui_.checkUseSSLForSMTP->setChecked(false);
|
||||
ui_.checkDoHEnabled->setChecked(true);
|
||||
ui_.checkIsPortFree->setChecked(true);
|
||||
|
||||
ui_.checkCacheOnDiskEnabled->setChecked(true);
|
||||
QString const cacheDir = QDir(tmpDir).absoluteFilePath("cache");
|
||||
QDir().mkpath(cacheDir);
|
||||
ui_.editDiskCachePath->setText(QDir::toNativeSeparators(cacheDir));
|
||||
ui_.checkNextCacheChangeWillSucceed->setChecked(true);
|
||||
ui_.comboCacheError->setCurrentIndex(0);
|
||||
|
||||
ui_.checkAutomaticUpdate->setChecked(true);
|
||||
}
|
||||
|
||||
@ -1,94 +0,0 @@
|
||||
// Copyright (c) 2022 Proton AG
|
||||
//
|
||||
// This file is part of Proton Mail Bridge.
|
||||
//
|
||||
// Proton Mail Bridge is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Proton Mail Bridge is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
#ifndef BRIDGE_GUI_TESTER_GENERAL_TAB_H
|
||||
#define BRIDGE_GUI_TESTER_GENERAL_TAB_H
|
||||
|
||||
|
||||
#include "Tab/ui_SettingsTab.h"
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \brief The 'General' tab of the main window.
|
||||
//****************************************************************************************************************************************************
|
||||
class SettingsTab : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public: // member functions.
|
||||
explicit SettingsTab(QWidget *parent = nullptr); ///< Default constructor.
|
||||
SettingsTab(SettingsTab const &) = delete; ///< Disabled copy-constructor.
|
||||
SettingsTab(SettingsTab &&) = delete; ///< Disabled assignment copy-constructor.
|
||||
~SettingsTab() = default; ///< Destructor.
|
||||
SettingsTab &operator=(SettingsTab const &) = delete; ///< Disabled assignment operator.
|
||||
SettingsTab &operator=(SettingsTab &&) = delete; ///< Disabled move assignment operator.
|
||||
|
||||
QString bridgeVersion() const; ///< Get the Bridge version.
|
||||
QString os() const; ///< Return the OS string.
|
||||
QString currentEmailClient() const; ///< Return the content of the current email client
|
||||
void setGUIReady(bool ready); ///< Set the GUI as ready.
|
||||
bool showOnStartup() const; ///< Get the value for the 'Show On Startup' check.
|
||||
bool showSplashScreen() const; ///< Get the value for the 'Show Splash Screen' check.
|
||||
bool isFirstGUIStart() const; ///< Get the value for the 'Is First GUI Start' check.
|
||||
bool isAutostartOn() const; ///< Get the value for the 'Autostart' check.
|
||||
bool isBetaEnabled() const; ///< Get the value for the 'Beta Enabled' check.
|
||||
bool isAllMailVisible() const; ///< Get the value for the 'All Mail Visible' check.
|
||||
QString colorSchemeName() const; ///< Get the value of the 'Use Dark Theme' checkbox.
|
||||
qint32 eventDelayMs() const; ///< Get the delay for sending automatically generated events.
|
||||
QString logsPath() const; ///< Get the content of the 'Logs Path' edit.
|
||||
QString licensePath() const; ///< Get the content of the 'License Path' edit.
|
||||
QString releaseNotesPageLink() const; ///< Get the content of the 'Release Notes Page Link' edit.
|
||||
QString dependencyLicenseLink() const; ///< Get the content of the 'Dependency License Link' edit.
|
||||
QString landingPageLink() const; ///< Get the content of the 'Landing Page Link' edit.
|
||||
bool nextBugReportWillSucceed() const; ///< Get the status of the 'Next Bug Report Will Fail' check box.
|
||||
QString hostname() const; ///< Get the value of the 'Hostname' edit.
|
||||
qint32 imapPort(); ///< Get the value of the IMAP port spin.
|
||||
qint32 smtpPort(); ///< Get the value of the SMTP port spin.
|
||||
bool useSSLForSMTP() const; ///< Get the value for the 'Use SSL for SMTP' check box.
|
||||
bool isDoHEnabled() const; ///< Get the value for the 'DoH Enabled' check box.
|
||||
bool isPortFree() const; ///< Get the value for the "Is Port Free" check box.
|
||||
bool isCacheOnDiskEnabled() const; ///< get the value for the 'Cache On Disk Enabled' check box.
|
||||
QString diskCachePath() const; ///< Get the value for the 'Disk Cache Path' edit.
|
||||
bool nextCacheChangeWillSucceed() const; ///< Get the value for the 'Next Cache Change will succeed' edit.
|
||||
qint32 cacheError() const; ///< Return the index of the selected cache error.
|
||||
bool isAutomaticUpdateOn() const; ///<Get the value for the 'Automatic Update' check box.
|
||||
|
||||
public: // slots
|
||||
void updateGUIState(); ///< Update the GUI state.
|
||||
void setIsStreaming(bool isStreaming); ///< Set the isStreamingEvents value.
|
||||
void setClientPlatform(QString const &clientPlatform); ///< Set the client platform.
|
||||
void setIsAutostartOn(bool on); ///< Set the value for the 'Autostart' check box.
|
||||
void setIsBetaEnabled(bool enabled); ///< Set the value for the 'Beta Enabled' check box.
|
||||
void setIsAllMailVisible(bool visible); ///< Set the value for the 'All Mail Visible' check box.
|
||||
void setColorSchemeName(QString const &name); ///< Set the value for the 'Use Dark Theme' check box.
|
||||
void setBugReport(QString const &osType, QString const &osVersion, QString const &emailClient, QString const &address, QString const &description,
|
||||
bool includeLogs); ///< Set the content of the bug report box.
|
||||
void changePorts(qint32 imapPort, qint32 smtpPort); ///< Change the IMAP and SMTP ports.
|
||||
void setUseSSLForSMTP(bool use); ///< Set the value for the 'Use SSL for SMTP' check box.
|
||||
void setIsDoHEnabled(bool enabled); ///< Set the value for the 'DoH Enabled' check box.
|
||||
void changeLocalCache(bool enabled, QString const &path); ///< Set the value for the 'Cache On Disk Enabled' check box.
|
||||
void setIsAutomaticUpdateOn(bool on); ///< Set the value for the 'Automatic Update' check box.
|
||||
|
||||
private: // member functions.
|
||||
void resetUI(); ///< Reset the widget.
|
||||
|
||||
private: // data members.
|
||||
Ui::SettingsTab ui_; ///< The GUI for the tab
|
||||
};
|
||||
|
||||
|
||||
#endif //BRIDGE_GUI_TESTER_GENERAL_TAB_H
|
||||
@ -1,866 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>SettingsTab</class>
|
||||
<widget class="QWidget" name="SettingsTab">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1066</width>
|
||||
<height>808</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_5">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupVersion">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Version Info</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<widget class="QLabel" name="labelVersion">
|
||||
<property name="text">
|
||||
<string>Bridge Version</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="editVersion"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="labelOS">
|
||||
<property name="text">
|
||||
<string>OS</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="comboOS">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">darwin</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">linux</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">windows</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="labelCurrentEmailClient">
|
||||
<property name="text">
|
||||
<string>Current Email Client</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="editCurrentEmailClient">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupGeneral">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>General Settings</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="0" column="0">
|
||||
<widget class="QCheckBox" name="checkShowOnStartup">
|
||||
<property name="text">
|
||||
<string>Show On Startup</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QCheckBox" name="checkShowSplashScreen">
|
||||
<property name="text">
|
||||
<string>Show Splash Screen</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QCheckBox" name="checkIsFirstGUIStart">
|
||||
<property name="text">
|
||||
<string>Is FIrst GUI Start</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QCheckBox" name="checkAutostart">
|
||||
<property name="text">
|
||||
<string>Autostart</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QCheckBox" name="checkBetaEnabled">
|
||||
<property name="text">
|
||||
<string>Beta Enabled</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QCheckBox" name="checkAutomaticUpdate">
|
||||
<property name="text">
|
||||
<string>Automatic Update</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QCheckBox" name="checkDarkTheme">
|
||||
<property name="text">
|
||||
<string>Dark Theme</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QCheckBox" name="checkAllMailVisible">
|
||||
<property name="text">
|
||||
<string>Show 'All Mail'</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupMail">
|
||||
<property name="title">
|
||||
<string>Mail</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_6">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_6" stretch="0,0">
|
||||
<item>
|
||||
<widget class="QLabel" name="labelHostname">
|
||||
<property name="text">
|
||||
<string>Hostname</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="editHostname">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>200</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_7" stretch="0,0,0,0,1">
|
||||
<item>
|
||||
<widget class="QLabel" name="labelMAP">
|
||||
<property name="text">
|
||||
<string>IMAP Port</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="spinPortIMAP">
|
||||
<property name="buttonSymbols">
|
||||
<enum>QAbstractSpinBox::NoButtons</enum>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>65535</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="labelSMTP">
|
||||
<property name="text">
|
||||
<string>SMTP Port</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="spinPortSMTP">
|
||||
<property name="buttonSymbols">
|
||||
<enum>QAbstractSpinBox::NoButtons</enum>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>65535</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkUseSSLForSMTP">
|
||||
<property name="text">
|
||||
<string>Use SSL For SMTP</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkDoHEnabled">
|
||||
<property name="text">
|
||||
<string>DoH Enabled</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupPaths">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Paths && Links</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="labelLogsPath">
|
||||
<property name="text">
|
||||
<string>Logs Path</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="editLogsPath"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="labelLicensePath">
|
||||
<property name="text">
|
||||
<string>License Path</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="editLicensePath"/>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="labelReleaseNotesLink">
|
||||
<property name="text">
|
||||
<string>Release Notes Page Link</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="editReleaseNotesLink"/>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="labelDependencyLicenseLink">
|
||||
<property name="text">
|
||||
<string>Dependency License Link</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLineEdit" name="editDependencyLicenseLink"/>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="labelLandingPageLink">
|
||||
<property name="text">
|
||||
<string>Landing Page Link</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QLineEdit" name="editLandingPageLink"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupCache">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Cache</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_7">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkCacheOnDiskEnabled">
|
||||
<property name="text">
|
||||
<string>Cache On Disk Enabled</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_10">
|
||||
<item>
|
||||
<widget class="QLabel" name="labelDiskCachePath">
|
||||
<property name="text">
|
||||
<string>Disk Cache Path</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="editDiskCachePath"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupStatus">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Status</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QLabel" name="labelGUIReadyTitle">
|
||||
<property name="text">
|
||||
<string>GUI Ready:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="labelGUIReadyValue">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>1</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
<item>
|
||||
<widget class="QLabel" name="labelStreamingTitle">
|
||||
<property name="text">
|
||||
<string>Streaming: </string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="labelStreamingValue">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="labelClientPlatformTitle">
|
||||
<property name="text">
|
||||
<string>Client Platform: </string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="labelClientPlatformValue">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBugReport">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Bug Report</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<item row="0" column="3">
|
||||
<widget class="QLineEdit" name="editOSVersion">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="baseSize">
|
||||
<size>
|
||||
<width>250</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="3">
|
||||
<widget class="QLineEdit" name="editAddress">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="labelOSType">
|
||||
<property name="text">
|
||||
<string>OS Type</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="labelIncludeLogs">
|
||||
<property name="text">
|
||||
<string>Include Logs</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QLabel" name="labelAddress">
|
||||
<property name="text">
|
||||
<string>Address</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QLabel" name="labelOSVersion">
|
||||
<property name="text">
|
||||
<string>OS Version</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="editOSType">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="baseSize">
|
||||
<size>
|
||||
<width>250</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1" colspan="3">
|
||||
<widget class="QLabel" name="labelIncludeLogsValue">
|
||||
<property name="text">
|
||||
<string>?</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="labelDescription">
|
||||
<property name="text">
|
||||
<string>Description</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="editEmailClient">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="labelEmailClient">
|
||||
<property name="text">
|
||||
<string>Email Cient</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1" colspan="4">
|
||||
<widget class="QPlainTextEdit" name="editDescription">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupApp">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Events && Errors</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_8">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_11">
|
||||
<item>
|
||||
<widget class="QLabel" name="labelEventDelay">
|
||||
<property name="toolTip">
|
||||
<string>Delay applied before sending automatically generated events</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Delay for asynchronous events</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="spinEventDelay">
|
||||
<property name="suffix">
|
||||
<string> ms</string>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>3600000</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>1000</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_5">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>1</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_9">
|
||||
<item>
|
||||
<widget class="QPushButton" name="buttonInternetOff">
|
||||
<property name="text">
|
||||
<string>Internet Off</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>10</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="buttonInternetOn">
|
||||
<property name="text">
|
||||
<string>Internet On</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>10</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="buttonShowMainWindow">
|
||||
<property name="text">
|
||||
<string>Show Main Window</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkIsPortFree">
|
||||
<property name="text">
|
||||
<string>Reply true to the next 'Is Port Free' request.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_8">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkNextCacheChangeWillSucceed">
|
||||
<property name="text">
|
||||
<string>Next Cache Change will succeed</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_6">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>1</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="comboCacheError">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Cache Unavailable</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Can't Move Cache</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Disk Full</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkNextBugReportWillSucceed">
|
||||
<property name="text">
|
||||
<string>Next Bug Report Will Succeed</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>editVersion</tabstop>
|
||||
<tabstop>comboOS</tabstop>
|
||||
<tabstop>editCurrentEmailClient</tabstop>
|
||||
<tabstop>checkShowOnStartup</tabstop>
|
||||
<tabstop>checkShowSplashScreen</tabstop>
|
||||
<tabstop>checkIsFirstGUIStart</tabstop>
|
||||
<tabstop>checkAutostart</tabstop>
|
||||
<tabstop>checkBetaEnabled</tabstop>
|
||||
<tabstop>checkAllMailVisible</tabstop>
|
||||
<tabstop>checkDarkTheme</tabstop>
|
||||
<tabstop>checkAutomaticUpdate</tabstop>
|
||||
<tabstop>editHostname</tabstop>
|
||||
<tabstop>spinPortIMAP</tabstop>
|
||||
<tabstop>spinPortSMTP</tabstop>
|
||||
<tabstop>checkUseSSLForSMTP</tabstop>
|
||||
<tabstop>checkDoHEnabled</tabstop>
|
||||
<tabstop>editLogsPath</tabstop>
|
||||
<tabstop>editLicensePath</tabstop>
|
||||
<tabstop>editReleaseNotesLink</tabstop>
|
||||
<tabstop>editDependencyLicenseLink</tabstop>
|
||||
<tabstop>editLandingPageLink</tabstop>
|
||||
<tabstop>checkCacheOnDiskEnabled</tabstop>
|
||||
<tabstop>editDiskCachePath</tabstop>
|
||||
<tabstop>editOSType</tabstop>
|
||||
<tabstop>editOSVersion</tabstop>
|
||||
<tabstop>editEmailClient</tabstop>
|
||||
<tabstop>editAddress</tabstop>
|
||||
<tabstop>editDescription</tabstop>
|
||||
<tabstop>spinEventDelay</tabstop>
|
||||
<tabstop>buttonInternetOff</tabstop>
|
||||
<tabstop>buttonInternetOn</tabstop>
|
||||
<tabstop>buttonShowMainWindow</tabstop>
|
||||
<tabstop>checkIsPortFree</tabstop>
|
||||
<tabstop>checkNextCacheChangeWillSucceed</tabstop>
|
||||
<tabstop>comboCacheError</tabstop>
|
||||
<tabstop>checkNextBugReportWillSucceed</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@ -1,329 +0,0 @@
|
||||
// Copyright (c) 2022 Proton AG
|
||||
//
|
||||
// This file is part of Proton Mail Bridge.
|
||||
//
|
||||
// Proton Mail Bridge is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Proton Mail Bridge is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
#include "UsersTab.h"
|
||||
#include "MainWindow.h"
|
||||
#include "UserDialog.h"
|
||||
#include <bridgepp/BridgeUtils.h>
|
||||
#include <bridgepp/Exception/Exception.h>
|
||||
#include <bridgepp/GRPC/EventFactory.h>
|
||||
|
||||
|
||||
using namespace bridgepp;
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] parent The parent widget of the tab.
|
||||
//****************************************************************************************************************************************************
|
||||
UsersTab::UsersTab(QWidget *parent)
|
||||
: QWidget(parent)
|
||||
, users_(nullptr)
|
||||
{
|
||||
ui_.setupUi(this);
|
||||
|
||||
ui_.tableUserList->setModel(&users_);
|
||||
|
||||
QItemSelectionModel *model = ui_.tableUserList->selectionModel();
|
||||
if (!model)
|
||||
throw Exception("Could not get user table selection model.");
|
||||
connect(model, &QItemSelectionModel::selectionChanged, this, &UsersTab::onSelectionChanged);
|
||||
|
||||
ui_.tableUserList->setColumnWidth(0, 150);
|
||||
ui_.tableUserList->setColumnWidth(1, 250);
|
||||
ui_.tableUserList->setColumnWidth(2, 350);
|
||||
|
||||
connect(ui_.buttonNewUser, &QPushButton::clicked, this, &UsersTab::onAddUserButton);
|
||||
connect(ui_.buttonEditUser, &QPushButton::clicked, this, &UsersTab::onEditUserButton);
|
||||
connect(ui_.tableUserList, &QTableView::doubleClicked, this, &UsersTab::onEditUserButton);
|
||||
connect(ui_.buttonRemoveUser, &QPushButton::clicked, this, &UsersTab::onRemoveUserButton);
|
||||
connect(ui_.checkUsernamePasswordError, &QCheckBox::toggled, this, &UsersTab::updateGUIState);
|
||||
|
||||
users_.append(randomUser());
|
||||
|
||||
this->updateGUIState();
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
//
|
||||
//****************************************************************************************************************************************************
|
||||
void UsersTab::onAddUserButton()
|
||||
{
|
||||
SPUser user = randomUser();
|
||||
UserDialog dialog(user, this);
|
||||
if (QDialog::Accepted != dialog.exec())
|
||||
return;
|
||||
users_.append(user);
|
||||
GRPCService &grpc = app().grpc();
|
||||
if (grpc.isStreaming())
|
||||
grpc.sendEvent(newLoginFinishedEvent(user->id()));
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
//
|
||||
//****************************************************************************************************************************************************
|
||||
void UsersTab::onEditUserButton()
|
||||
{
|
||||
int index = selectedIndex();
|
||||
if ((index < 0) || (index >= users_.userCount()))
|
||||
return;
|
||||
|
||||
SPUser user = this->selectedUser();
|
||||
UserDialog dialog(user, this);
|
||||
if (QDialog::Accepted != dialog.exec())
|
||||
return;
|
||||
|
||||
users_.touch(index);
|
||||
GRPCService &grpc = app().grpc();
|
||||
if (grpc.isStreaming())
|
||||
grpc.sendEvent(newUserChangedEvent(user->id()));
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
//
|
||||
//****************************************************************************************************************************************************
|
||||
void UsersTab::onRemoveUserButton()
|
||||
{
|
||||
int index = selectedIndex();
|
||||
if ((index < 0) || (index >= users_.userCount()))
|
||||
return;
|
||||
|
||||
SPUser const user = users_.userAtIndex(index);
|
||||
users_.remove(index);
|
||||
GRPCService &grpc = app().grpc();
|
||||
if (grpc.isStreaming())
|
||||
grpc.sendEvent(newUserChangedEvent(user->id()));
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
//
|
||||
//****************************************************************************************************************************************************
|
||||
void UsersTab::onSelectionChanged(QItemSelection, QItemSelection)
|
||||
{
|
||||
this->updateGUIState();
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
//
|
||||
//****************************************************************************************************************************************************
|
||||
void UsersTab::updateGUIState()
|
||||
{
|
||||
bool const hasSelectedUser = ui_.tableUserList->selectionModel()->hasSelection();
|
||||
ui_.buttonEditUser->setEnabled(hasSelectedUser);
|
||||
ui_.buttonRemoveUser->setEnabled(hasSelectedUser);
|
||||
ui_.editUsernamePasswordError->setEnabled(ui_.checkUsernamePasswordError->isChecked());
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
//
|
||||
//****************************************************************************************************************************************************
|
||||
qint32 UsersTab::selectedIndex() const
|
||||
{
|
||||
return ui_.tableUserList->selectionModel()->hasSelection() ? ui_.tableUserList->currentIndex().row() : -1;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return The selected user.
|
||||
/// \return A null pointer if no user is selected.
|
||||
//****************************************************************************************************************************************************
|
||||
bridgepp::SPUser UsersTab::selectedUser()
|
||||
{
|
||||
return users_.userAtIndex(this->selectedIndex());
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return The list of users.
|
||||
//****************************************************************************************************************************************************
|
||||
UserTable &UsersTab::userTable()
|
||||
{
|
||||
return users_;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] userID The userID.
|
||||
/// \return The user with the given userID.
|
||||
/// \return A null pointer if the user is not in the list.
|
||||
//****************************************************************************************************************************************************
|
||||
bridgepp::SPUser UsersTab::userWithID(QString const &userID)
|
||||
{
|
||||
return users_.userWithID(userID);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return true iff the next login attempt should trigger a username/password error.
|
||||
//****************************************************************************************************************************************************
|
||||
bool UsersTab::nextUserUsernamePasswordError() const
|
||||
{
|
||||
return ui_.checkUsernamePasswordError->isChecked();
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return true iff the next login attempt should trigger a free user error.
|
||||
//****************************************************************************************************************************************************
|
||||
bool UsersTab::nextUserFreeUserError() const
|
||||
{
|
||||
return ui_.checkFreeUserError->isChecked();
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return true iff the next login attempt will require 2FA.
|
||||
//****************************************************************************************************************************************************
|
||||
bool UsersTab::nextUserTFARequired() const
|
||||
{
|
||||
return ui_.checkTFARequired->isChecked();
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return true iff the next login attempt should trigger a 2FA error.
|
||||
//****************************************************************************************************************************************************
|
||||
bool UsersTab::nextUserTFAError() const
|
||||
{
|
||||
return ui_.checkTFAError->isChecked();
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return true iff the next login attempt should trigger a 2FA error with abort.
|
||||
//****************************************************************************************************************************************************
|
||||
bool UsersTab::nextUserTFAAbort() const
|
||||
{
|
||||
return ui_.checkTFAAbort->isChecked();
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return true iff the next login attempt will require a 2nd password.
|
||||
//****************************************************************************************************************************************************
|
||||
bool UsersTab::nextUserTwoPasswordsRequired() const
|
||||
{
|
||||
return ui_.checkTwoPasswordsRequired->isChecked();
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return true iff the next login attempt should trigger a 2nd password error.
|
||||
//****************************************************************************************************************************************************
|
||||
bool UsersTab::nextUserTwoPasswordsError() const
|
||||
{
|
||||
return ui_.checkTwoPasswordsError->isChecked();
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return true iff the next login attempt should trigger a 2nd password error with abort.
|
||||
//****************************************************************************************************************************************************
|
||||
bool UsersTab::nextUserTwoPasswordsAbort() const
|
||||
{
|
||||
return ui_.checkTwoPasswordsAbort->isChecked();
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return true iff the next login attempt should trigger a 2nd password error with abort.
|
||||
//****************************************************************************************************************************************************
|
||||
bool UsersTab::nextUserAlreadyLoggedIn() const
|
||||
{
|
||||
return ui_.checkAlreadyLoggedIn->isChecked();
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return the message for the username/password error.
|
||||
//****************************************************************************************************************************************************
|
||||
QString UsersTab::usernamePasswordErrorMessage() const
|
||||
{
|
||||
return ui_.editUsernamePasswordError->text();
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] userID The userID.
|
||||
/// \param[in] makeItActive Should split mode be activated.
|
||||
//****************************************************************************************************************************************************
|
||||
void UsersTab::setUserSplitMode(QString const &userID, bool makeItActive)
|
||||
{
|
||||
qint32 const index = users_.indexOfUser(userID);
|
||||
SPUser const user = users_.userAtIndex(index);
|
||||
if (!user)
|
||||
{
|
||||
app().log().error(QString("%1 failed. unknown user %1").arg(__FUNCTION__, userID));
|
||||
return;
|
||||
}
|
||||
user->setSplitMode(makeItActive);
|
||||
users_.touch(index);
|
||||
MainWindow &mainWindow = app().mainWindow();
|
||||
mainWindow.sendDelayedEvent(newUserChangedEvent(userID));
|
||||
mainWindow.sendDelayedEvent(newToggleSplitModeFinishedEvent(userID));
|
||||
}
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] userID The userID.
|
||||
//****************************************************************************************************************************************************
|
||||
void UsersTab::logoutUser(QString const &userID)
|
||||
{
|
||||
qint32 const index = users_.indexOfUser(userID);
|
||||
SPUser const user = users_.userAtIndex(index);
|
||||
if (!user)
|
||||
{
|
||||
app().log().error(QString("%1 failed. unknown user %1").arg(__FUNCTION__, userID));
|
||||
return;
|
||||
}
|
||||
user->setLoggedIn(false);
|
||||
users_.touch(index);
|
||||
app().mainWindow().sendDelayedEvent(newUserChangedEvent(userID));
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] userID The userID.
|
||||
//****************************************************************************************************************************************************
|
||||
void UsersTab::removeUser(QString const &userID)
|
||||
{
|
||||
qint32 const index = users_.indexOfUser(userID);
|
||||
SPUser const user = users_.userAtIndex(index);
|
||||
if (!user)
|
||||
{
|
||||
app().log().error(QString("%1 failed. unknown user %1").arg(__FUNCTION__, userID));
|
||||
return;
|
||||
}
|
||||
users_.remove(index);
|
||||
app().mainWindow().sendDelayedEvent(newUserChangedEvent(userID));
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] userID The userID.
|
||||
/// \param[in] address The address.
|
||||
//****************************************************************************************************************************************************
|
||||
void UsersTab::configureUserAppleMail(QString const &userID, QString const &address)
|
||||
{
|
||||
app().log().info(QString("Apple mail configuration was requested for user %1, address %2").arg(userID, address));
|
||||
|
||||
}
|
||||
@ -1,76 +0,0 @@
|
||||
// Copyright (c) 2022 Proton AG
|
||||
//
|
||||
// This file is part of Proton Mail Bridge.
|
||||
//
|
||||
// Proton Mail Bridge is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Proton Mail Bridge is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
#ifndef BRIDGE_GUI_TESTER_USERS_TAB_H
|
||||
#define BRIDGE_GUI_TESTER_USERS_TAB_H
|
||||
|
||||
|
||||
#include "Tabs/ui_UsersTab.h"
|
||||
#include "UserTable.h"
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \brief The 'Users' tab of the main window.
|
||||
//****************************************************************************************************************************************************
|
||||
class UsersTab : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public: // member functions.
|
||||
explicit UsersTab(QWidget *parent = nullptr); ///< Default constructor.
|
||||
UsersTab(UsersTab const &) = delete; ///< Disabled copy-constructor.
|
||||
UsersTab(UsersTab &&) = delete; ///< Disabled assignment copy-constructor.
|
||||
~UsersTab() override = default; ///< Destructor.
|
||||
UsersTab &operator=(UsersTab const &) = delete; ///< Disabled assignment operator.
|
||||
UsersTab &operator=(UsersTab &&) = delete; ///< Disabled move assignment operator.
|
||||
UserTable &userTable(); ///< Returns a reference to the user table.
|
||||
bridgepp::SPUser userWithID(QString const &userID); ///< Get the user with the given ID.
|
||||
bool nextUserUsernamePasswordError() const; ///< Check if next user login should trigger a username/password error.
|
||||
bool nextUserFreeUserError() const; ///< Check if next user login should trigger a Free user error.
|
||||
bool nextUserTFARequired() const; ///< Check if next user login should requires 2FA.
|
||||
bool nextUserTFAError() const; ///< Check if next user login should trigger 2FA error
|
||||
bool nextUserTFAAbort() const; ///< Check if next user login should trigger 2FA abort.
|
||||
bool nextUserTwoPasswordsRequired() const; ///< Check if next user login requires 2nd password
|
||||
bool nextUserTwoPasswordsError() const; ///< Check if next user login should trigger 2nd password error.
|
||||
bool nextUserTwoPasswordsAbort() const; ///< Check if next user login should trigger 2nd password abort.
|
||||
bool nextUserAlreadyLoggedIn() const; ///< Check if next user login should report user as already logged in.
|
||||
QString usernamePasswordErrorMessage() const; ///< Return the username password error message.
|
||||
|
||||
public slots:
|
||||
void setUserSplitMode(QString const &userID, bool makeItActive); ///< Slot for the split mode.
|
||||
void logoutUser(QString const &userID); ///< slot for the logging out of a user.
|
||||
void removeUser(QString const &userID); ///< Slot for the removal of a user.
|
||||
void configureUserAppleMail(QString const &userID, QString const &address); ///< Slot for the configuration of Apple mail.
|
||||
|
||||
private slots:
|
||||
void onAddUserButton(); ///< Add a user to the user list.
|
||||
void onEditUserButton(); ///< Edit the currently selected user.
|
||||
void onRemoveUserButton(); ///< Remove the currently selected user.
|
||||
void onSelectionChanged(QItemSelection, QItemSelection); ///< Slot for the change of the selection.
|
||||
void updateGUIState(); ///< Update the GUI state.
|
||||
|
||||
private: // member functions.
|
||||
qint32 selectedIndex() const; ///< Get the index of the selected row.
|
||||
bridgepp::SPUser selectedUser(); ///< Get the selected user.
|
||||
|
||||
private: // data members.
|
||||
Ui::UsersTab ui_ {}; ///< The UI for the tab.
|
||||
UserTable users_; ///< The User list.
|
||||
};
|
||||
|
||||
|
||||
#endif //BRIDGE_GUI_TESTER_USERS_TAB_H
|
||||
@ -1,195 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>UsersTab</class>
|
||||
<widget class="QWidget" name="UsersTab">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1225</width>
|
||||
<height>717</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout" stretch="1,0">
|
||||
<item>
|
||||
<widget class="QTableView" name="tableUserList">
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::SingleSelection</enum>
|
||||
</property>
|
||||
<property name="selectionBehavior">
|
||||
<enum>QAbstractItemView::SelectRows</enum>
|
||||
</property>
|
||||
<attribute name="horizontalHeaderStretchLastSection">
|
||||
<bool>true</bool>
|
||||
</attribute>
|
||||
<attribute name="verticalHeaderVisible">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QPushButton" name="buttonNewUser">
|
||||
<property name="text">
|
||||
<string>New User</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="buttonEditUser">
|
||||
<property name="text">
|
||||
<string>Edit User</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="buttonRemoveUser">
|
||||
<property name="text">
|
||||
<string>Remove User</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>100</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Next Login Attempt</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkUsernamePasswordError">
|
||||
<property name="text">
|
||||
<string>Username/password error:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>10</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="editUsernamePasswordError">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>200</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Username/password error.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkFreeUserError">
|
||||
<property name="text">
|
||||
<string>Free user error</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkTFARequired">
|
||||
<property name="text">
|
||||
<string>2FA required</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkTFAError">
|
||||
<property name="text">
|
||||
<string>2FA error</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkTFAAbort">
|
||||
<property name="text">
|
||||
<string>2FA abort</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkTwoPasswordsRequired">
|
||||
<property name="text">
|
||||
<string>2nd password required</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkTwoPasswordsError">
|
||||
<property name="text">
|
||||
<string>2nd password error</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkTwoPasswordsAbort">
|
||||
<property name="text">
|
||||
<string>2nd password abort</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkAlreadyLoggedIn">
|
||||
<property name="text">
|
||||
<string>Already logged in</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>buttonNewUser</tabstop>
|
||||
<tabstop>buttonEditUser</tabstop>
|
||||
<tabstop>buttonRemoveUser</tabstop>
|
||||
<tabstop>tableUserList</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@ -1,65 +0,0 @@
|
||||
// Copyright (c) 2022 Proton AG
|
||||
//
|
||||
// This file is part of Proton Mail Bridge.
|
||||
//
|
||||
// Proton Mail Bridge is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Proton Mail Bridge is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
#include "UserDialog.h"
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] user The user.
|
||||
/// \param[in] parent The parent widget of the dialog.
|
||||
//****************************************************************************************************************************************************
|
||||
UserDialog::UserDialog(bridgepp::SPUser &user, QWidget *parent)
|
||||
: QDialog(parent)
|
||||
, user_(user)
|
||||
{
|
||||
ui_.setupUi(this);
|
||||
|
||||
connect(ui_.buttonOK, &QPushButton::clicked, this, &UserDialog::onOK);
|
||||
connect(ui_.buttonCancel, &QPushButton::clicked, this, &UserDialog::reject);
|
||||
|
||||
ui_.editUserID->setText(user_->id());
|
||||
ui_.editUsername->setText(user_->username());
|
||||
ui_.editPassword->setText(user->password());
|
||||
ui_.editAddresses->setPlainText(user->addresses().join("\n"));
|
||||
ui_.editAvatarText->setText(user_->avatarText());
|
||||
ui_.checkLoggedIn->setChecked(user_->loggedIn());
|
||||
ui_.checkSplitMode->setChecked(user_->splitMode());
|
||||
ui_.checkSetupGuideSeen->setChecked(user_->setupGuideSeen());
|
||||
ui_.spinUsedBytes->setValue(user->usedBytes());
|
||||
ui_.spinTotalBytes->setValue(user->totalBytes());
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
//
|
||||
//****************************************************************************************************************************************************
|
||||
void UserDialog::onOK()
|
||||
{
|
||||
user_->setID(ui_.editUserID->text());
|
||||
user_->setUsername(ui_.editUsername->text());
|
||||
user_->setPassword(ui_.editPassword->text());
|
||||
user_->setAddresses(ui_.editAddresses->toPlainText().split(QRegularExpression(R"(\s+)"), Qt::SkipEmptyParts));
|
||||
user_->setAvatarText(ui_.editAvatarText->text());
|
||||
user_->setLoggedIn(ui_.checkLoggedIn->isChecked());
|
||||
user_->setSplitMode(ui_.checkSplitMode->isChecked());
|
||||
user_->setSetupGuideSeen(ui_.checkSetupGuideSeen->isChecked());
|
||||
user_->setUsedBytes(float(ui_.spinUsedBytes->value()));
|
||||
user_->setTotalBytes(float(ui_.spinTotalBytes->value()));
|
||||
|
||||
this->accept();
|
||||
}
|
||||
@ -1,49 +0,0 @@
|
||||
// Copyright (c) 2022 Proton AG
|
||||
//
|
||||
// This file is part of Proton Mail Bridge.
|
||||
//
|
||||
// Proton Mail Bridge is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Proton Mail Bridge is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
#ifndef BRIDGE_GUI_TESTER_USER_DIALOG_H
|
||||
#define BRIDGE_GUI_TESTER_USER_DIALOG_H
|
||||
|
||||
|
||||
#include "ui_UserDialog.h"
|
||||
#include <bridgepp/User/User.h>
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \brief User dialog class.
|
||||
//****************************************************************************************************************************************************
|
||||
class UserDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
public: // member functions.
|
||||
UserDialog(bridgepp::SPUser &user, QWidget *parent); ///< Default constructor.
|
||||
UserDialog(UserDialog const &) = delete; ///< Disabled copy-constructor.
|
||||
UserDialog(UserDialog &&) = delete; ///< Disabled assignment copy-constructor.
|
||||
~UserDialog() override = default; ///< Destructor.
|
||||
UserDialog &operator=(UserDialog const &) = delete; ///< Disabled assignment operator.
|
||||
UserDialog &operator=(UserDialog &&) = delete; ///< Disabled move assignment operator.
|
||||
|
||||
private slots:
|
||||
void onOK(); ///< Slot for the OK button.
|
||||
|
||||
private:
|
||||
Ui::UserDialog ui_ {}; ///< The UI for the dialog.
|
||||
bridgepp::SPUser user_; ///< The user
|
||||
};
|
||||
|
||||
|
||||
#endif //BRIDGE_GUI_TESTER_USER_DIALOG_H
|
||||
@ -1,220 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>UserDialog</class>
|
||||
<widget class="QDialog" name="UserDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>521</width>
|
||||
<height>432</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>User</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout" stretch="0,1,0">
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="labelAvatarText">
|
||||
<property name="text">
|
||||
<string>Avatar Text</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="labelPassword">
|
||||
<property name="text">
|
||||
<string>Password</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="labelUsername">
|
||||
<property name="text">
|
||||
<string>Account Name</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="labelUserID">
|
||||
<property name="text">
|
||||
<string>UserID</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="labelUsedBytes">
|
||||
<property name="text">
|
||||
<string>Used Bytes</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="checkSetupGuideSeen">
|
||||
<property name="text">
|
||||
<string>Setup Guide Seen</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="editPassword"/>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="labelTotalBytes">
|
||||
<property name="text">
|
||||
<string>Total Bytes</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QLineEdit" name="editAvatarText"/>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="labelAddresses">
|
||||
<property name="text">
|
||||
<string>Adresses</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QPlainTextEdit" name="editAddresses">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>100</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="baseSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>150</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="tabChangesFocus">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QDoubleSpinBox" name="spinUsedBytes">
|
||||
<property name="buttonSymbols">
|
||||
<enum>QAbstractSpinBox::NoButtons</enum>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>1000000000000000.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="editUserID">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="checkLoggedIn">
|
||||
<property name="text">
|
||||
<string>Logged in</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="editUsername"/>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QDoubleSpinBox" name="spinTotalBytes">
|
||||
<property name="buttonSymbols">
|
||||
<enum>QAbstractSpinBox::NoButtons</enum>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>1000000000000000.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="checkSplitMode">
|
||||
<property name="text">
|
||||
<string>Split Mode</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>1</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="buttonCancel">
|
||||
<property name="text">
|
||||
<string>&Cancel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="buttonOK">
|
||||
<property name="text">
|
||||
<string>&OK</string>
|
||||
</property>
|
||||
<property name="default">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>editUserID</tabstop>
|
||||
<tabstop>editUsername</tabstop>
|
||||
<tabstop>editPassword</tabstop>
|
||||
<tabstop>editAddresses</tabstop>
|
||||
<tabstop>editAvatarText</tabstop>
|
||||
<tabstop>spinUsedBytes</tabstop>
|
||||
<tabstop>spinTotalBytes</tabstop>
|
||||
<tabstop>checkLoggedIn</tabstop>
|
||||
<tabstop>checkSplitMode</tabstop>
|
||||
<tabstop>checkSetupGuideSeen</tabstop>
|
||||
<tabstop>buttonOK</tabstop>
|
||||
<tabstop>buttonCancel</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@ -1,209 +0,0 @@
|
||||
// Copyright (c) 2022 Proton AG
|
||||
//
|
||||
// This file is part of Proton Mail Bridge.
|
||||
//
|
||||
// Proton Mail Bridge is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Proton Mail Bridge is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
#include "UserTable.h"
|
||||
|
||||
|
||||
using namespace bridgepp;
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] parent The parent object of the class
|
||||
//****************************************************************************************************************************************************
|
||||
UserTable::UserTable(QObject *parent)
|
||||
: QAbstractTableModel(parent)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return The number of rows in the table.
|
||||
//****************************************************************************************************************************************************
|
||||
int UserTable::rowCount(QModelIndex const &) const
|
||||
{
|
||||
return users_.size();
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return The number of columns in the table.
|
||||
//****************************************************************************************************************************************************
|
||||
int UserTable::columnCount(QModelIndex const &) const
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] index The model index.
|
||||
/// \param[in] role The role to retrieve data for.
|
||||
/// \return The data for the role at the given index.
|
||||
//****************************************************************************************************************************************************
|
||||
QVariant UserTable::data(QModelIndex const &index, int role) const
|
||||
{
|
||||
int const row = index.row();
|
||||
if ((row < 0) || (row >= users_.size()) || (Qt::DisplayRole != role))
|
||||
return QVariant();
|
||||
|
||||
SPUser const user = users_[row];
|
||||
if (!user)
|
||||
return QVariant();
|
||||
|
||||
switch (index.column())
|
||||
{
|
||||
case 0:
|
||||
return user->property("username");
|
||||
case 1:
|
||||
return user->property("addresses").toStringList().join(" ");
|
||||
case 2:
|
||||
return user->property("id");
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] section The section (column).
|
||||
/// \param[in] orientation The orientation.
|
||||
/// \param[in] role The role to retrieve data
|
||||
//****************************************************************************************************************************************************
|
||||
QVariant UserTable::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
if (Qt::DisplayRole != role)
|
||||
return QAbstractTableModel::headerData(section, orientation, role);
|
||||
|
||||
if (Qt::Horizontal != orientation)
|
||||
return QString();
|
||||
|
||||
switch (section)
|
||||
{
|
||||
case 0:
|
||||
return "UserName";
|
||||
case 1:
|
||||
return "Addresses";
|
||||
case 2:
|
||||
return "UserID";
|
||||
default:
|
||||
return QString();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] user The user to add.
|
||||
//****************************************************************************************************************************************************
|
||||
void UserTable::append(SPUser const &user)
|
||||
{
|
||||
qint32 const count = users_.size();
|
||||
this->beginInsertRows(QModelIndex(), count, count);
|
||||
users_.append(user);
|
||||
this->endInsertRows();
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return The number of users in the table.
|
||||
//****************************************************************************************************************************************************
|
||||
qint32 UserTable::userCount() const
|
||||
{
|
||||
return users_.count();
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] index The index of the user in the list.
|
||||
/// \return the user at the given index.
|
||||
/// \return null if the index is out of bounds.
|
||||
//****************************************************************************************************************************************************
|
||||
bridgepp::SPUser UserTable::userAtIndex(qint32 index)
|
||||
{
|
||||
return isIndexValid(index) ? users_[index] : nullptr;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return The user with the given userID.
|
||||
/// \return A null pointer if the user is not in the list.
|
||||
//****************************************************************************************************************************************************
|
||||
bridgepp::SPUser UserTable::userWithID(QString const &userID)
|
||||
{
|
||||
QList<SPUser>::const_iterator it = std::find_if(users_.constBegin(), users_.constEnd(), [&userID](SPUser const& user) -> bool {
|
||||
return user->id() == userID;
|
||||
});
|
||||
|
||||
return it == users_.end() ? nullptr : *it;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] userID The userID.
|
||||
/// \return the index of the user.
|
||||
/// \return -1 if the user could not be found.
|
||||
//****************************************************************************************************************************************************
|
||||
qint32 UserTable::indexOfUser(QString const &userID)
|
||||
{
|
||||
QList<SPUser>::const_iterator it = std::find_if(users_.constBegin(), users_.constEnd(), [&userID](SPUser const& user) -> bool {
|
||||
return user->id() == userID;
|
||||
});
|
||||
|
||||
return it == users_.end() ? -1 : it - users_.constBegin();
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] index The index of the user in the list.
|
||||
//****************************************************************************************************************************************************
|
||||
void UserTable::touch(qint32 index)
|
||||
{
|
||||
if (isIndexValid(index))
|
||||
emit dataChanged(this->index(index, 0), this->index(index, this->columnCount(QModelIndex()) - 1));
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] index The index of the user in the list.
|
||||
//****************************************************************************************************************************************************
|
||||
void UserTable::remove(qint32 index)
|
||||
{
|
||||
if (!isIndexValid(index))
|
||||
return;
|
||||
|
||||
this->beginRemoveRows(QModelIndex(), index, index);
|
||||
users_.removeAt(index);
|
||||
this->endRemoveRows();
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return true iff the index is valid.
|
||||
//****************************************************************************************************************************************************
|
||||
bool UserTable::isIndexValid(qint32 index) const
|
||||
{
|
||||
return (index >= 0) && (index < users_.count());
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return The user list.
|
||||
//****************************************************************************************************************************************************
|
||||
QList<bridgepp::SPUser> UserTable::users() const
|
||||
{
|
||||
return users_;
|
||||
}
|
||||
@ -1,61 +0,0 @@
|
||||
// Copyright (c) 2022 Proton AG
|
||||
//
|
||||
// This file is part of Proton Mail Bridge.
|
||||
//
|
||||
// Proton Mail Bridge is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Proton Mail Bridge is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
|
||||
#ifndef BRIDGE_GUI_TESTER_USER_TABLE_H
|
||||
#define BRIDGE_GUI_TESTER_USER_TABLE_H
|
||||
|
||||
|
||||
#include <bridgepp/User/User.h>
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \brief User table model class
|
||||
//****************************************************************************************************************************************************
|
||||
|
||||
class UserTable : public QAbstractTableModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public: // member functions.
|
||||
explicit UserTable(QObject *parent); ///< Default constructor.
|
||||
UserTable(UserTable const &) = delete; ///< Disabled copy-constructor.
|
||||
UserTable(UserTable &&) = delete; ///< Disabled assignment copy-constructor.
|
||||
~UserTable() = default; ///< Destructor.
|
||||
UserTable &operator=(UserTable const &) = delete; ///< Disabled assignment operator.
|
||||
UserTable &operator=(UserTable &&) = delete; ///< Disabled move assignment operator.
|
||||
qint32 userCount() const; ///< Return the number of users in the table.
|
||||
void append(bridgepp::SPUser const& user); ///< Append a user.
|
||||
bridgepp::SPUser userAtIndex(qint32 index); ///< Return the user at the given index.
|
||||
bridgepp::SPUser userWithID(QString const &userID); ///< Return the user with a given id.
|
||||
qint32 indexOfUser(QString const& userID); ///< Return the index of a given User.
|
||||
void touch(qint32 index); ///< touch the user at a given index (indicates it has been modified).
|
||||
void remove(qint32 index); ///< Remove the user at a given index.
|
||||
QList<bridgepp::SPUser> users() const; ///< Return a copy of the user list.
|
||||
|
||||
private: // data members.
|
||||
int rowCount(QModelIndex const &parent) const override; ///< Get the number of rows in the table.
|
||||
int columnCount(QModelIndex const &parent) const override; ///< Get the number of columns in the table.
|
||||
QVariant data(QModelIndex const &index, int role) const override; ///< Get the data for a role at a given index.
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role) const override; ///< Get header data.
|
||||
bool isIndexValid(qint32 index) const; ///< return true iff the index is valid.
|
||||
|
||||
public:
|
||||
QList<bridgepp::SPUser> users_;
|
||||
};
|
||||
|
||||
|
||||
#endif //BRIDGE_GUI_TESTER_USER_TABLE_H
|
||||
@ -1,92 +0,0 @@
|
||||
// Copyright (c) 2022 Proton AG
|
||||
//
|
||||
// This file is part of Proton Mail Bridge.
|
||||
//
|
||||
// Proton Mail Bridge is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Proton Mail Bridge is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
#include "MainWindow.h"
|
||||
#include "AppController.h"
|
||||
#include "GRPCServerWorker.h"
|
||||
#include <bridgepp/Exception/Exception.h>
|
||||
#include <bridgepp/Worker/Overseer.h>
|
||||
|
||||
|
||||
#ifndef BRIDGE_APP_VERSION
|
||||
#error "BRIDGE_APP_VERSION is not defined"
|
||||
#endif
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
|
||||
QString const applicationName = "Proton Mail Bridge GUI Tester"; ///< The name of the application.
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
using namespace bridgepp;
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] argc The number of command-line arguments.
|
||||
/// \param[in] argv The list of command-line arguments.
|
||||
/// \return The exit code for the application.
|
||||
//****************************************************************************************************************************************************
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
|
||||
try
|
||||
{
|
||||
QApplication a(argc, argv);
|
||||
QApplication::setApplicationName(applicationName);
|
||||
QApplication::setOrganizationName("Proton AG");
|
||||
QApplication::setOrganizationDomain("proton.ch");
|
||||
QApplication::setQuitOnLastWindowClosed(true);
|
||||
|
||||
Log& log = app().log();
|
||||
log.setEchoInConsole(true);
|
||||
log.info(QString("%1 started.").arg(applicationName));
|
||||
|
||||
MainWindow window(nullptr);
|
||||
app().setMainWindow(&window);
|
||||
window.setWindowTitle(QApplication::applicationName());
|
||||
window.show();
|
||||
|
||||
auto *serverWorker = new GRPCServerWorker(nullptr);
|
||||
QObject::connect(serverWorker, &Worker::started, []() { app().log().info("Server worker started."); });
|
||||
QObject::connect(serverWorker, &Worker::finished, []() { app().log().info("Server worker finished."); });
|
||||
QObject::connect(serverWorker, &Worker::error, [&](QString const &message) { app().log().error(message); qApp->exit(EXIT_FAILURE); });
|
||||
UPOverseer overseer = std::make_unique<Overseer>(serverWorker, nullptr);
|
||||
overseer->startWorker(true);
|
||||
|
||||
qint32 const exitCode = QApplication::exec();
|
||||
|
||||
serverWorker->stop();
|
||||
if (!overseer->wait(5000))
|
||||
log.warn("gRPC server took too long to finish.");
|
||||
|
||||
app().log().info(QString("%1 exiting with code %2.").arg(applicationName).arg(exitCode));
|
||||
return exitCode;
|
||||
}
|
||||
catch (Exception const &e)
|
||||
{
|
||||
QTextStream(stderr) << QString("A fatal error occurred: %1\n").arg(e.qwhat());
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,68 +0,0 @@
|
||||
// Copyright (c) 2022 Proton AG
|
||||
//
|
||||
// This file is part of Proton Mail Bridge.
|
||||
//
|
||||
// Proton Mail Bridge is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Proton Mail Bridge is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
#include "AppController.h"
|
||||
#include "QMLBackend.h"
|
||||
#include <bridgepp/GRPC/GRPCClient.h>
|
||||
#include <bridgepp/Exception/Exception.h>
|
||||
#include <bridgepp/ProcessMonitor.h>
|
||||
#include <bridgepp/Log/Log.h>
|
||||
|
||||
|
||||
using namespace bridgepp;
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return The AppController instance.
|
||||
//****************************************************************************************************************************************************
|
||||
AppController &app()
|
||||
{
|
||||
static AppController app;
|
||||
return app;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
//
|
||||
//****************************************************************************************************************************************************
|
||||
AppController::AppController()
|
||||
: backend_(std::make_unique<QMLBackend>())
|
||||
, grpc_(std::make_unique<GRPCClient>())
|
||||
, log_(std::make_unique<Log>())
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return The bridge worker, which can be null if the application was run in 'attach' mode (-a command-line switch).
|
||||
//****************************************************************************************************************************************************
|
||||
ProcessMonitor *AppController::bridgeMonitor() const
|
||||
{
|
||||
if (!bridgeOverseer_)
|
||||
return nullptr;
|
||||
|
||||
// null bridgeOverseer is OK, it means we run in 'attached' mode (app attached to an already runnning instance of Bridge).
|
||||
// but if bridgeOverseer is not null, its attached worker must be a valid ProcessMonitor instance.
|
||||
auto *monitor = dynamic_cast<ProcessMonitor*>(bridgeOverseer_->worker());
|
||||
if (!monitor)
|
||||
throw Exception("Could not retrieve bridge monitor");
|
||||
|
||||
return monitor;
|
||||
}
|
||||
|
||||
|
||||
@ -1,69 +0,0 @@
|
||||
// Copyright (c) 2022 Proton AG
|
||||
//
|
||||
// This file is part of Proton Mail Bridge.
|
||||
//
|
||||
// Proton Mail Bridge is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Proton Mail Bridge is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
#ifndef BRIDGE_GUI_APP_CONTROLLER_H
|
||||
#define BRIDGE_GUI_APP_CONTROLLER_H
|
||||
|
||||
|
||||
class QMLBackend;
|
||||
|
||||
|
||||
namespace bridgepp
|
||||
{
|
||||
class Log;
|
||||
class Overseer;
|
||||
class GRPCClient;
|
||||
class ProcessMonitor;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \brief App controller class.
|
||||
//****************************************************************************************************************************************************
|
||||
class AppController: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
friend AppController& app();
|
||||
|
||||
public: // member functions.
|
||||
AppController(AppController const&) = delete; ///< Disabled copy-constructor.
|
||||
AppController(AppController&&) = delete; ///< Disabled assignment copy-constructor.
|
||||
~AppController() override = default; ///< Destructor.
|
||||
AppController& operator=(AppController const&) = delete; ///< Disabled assignment operator.
|
||||
AppController& operator=(AppController&&) = delete; ///< Disabled move assignment operator.
|
||||
QMLBackend& backend() { return *backend_; } ///< Return a reference to the backend.
|
||||
bridgepp::GRPCClient& grpc() { return *grpc_; } ///< Return a reference to the GRPC client.
|
||||
bridgepp::Log& log() { return *log_; } ///< Return a reference to the log.
|
||||
std::unique_ptr<bridgepp::Overseer>& bridgeOverseer() { return bridgeOverseer_; }; ///< Returns a reference the bridge overseer
|
||||
bridgepp::ProcessMonitor* bridgeMonitor() const; ///< Return the bridge worker.
|
||||
|
||||
private: // member functions
|
||||
AppController(); ///< Default constructor.
|
||||
|
||||
private: // data members
|
||||
std::unique_ptr<QMLBackend> backend_; ///< The backend.
|
||||
std::unique_ptr<bridgepp::GRPCClient> grpc_; ///< The RPC client.
|
||||
std::unique_ptr<bridgepp::Log> log_; ///< The log.
|
||||
std::unique_ptr<bridgepp::Overseer> bridgeOverseer_; ///< The overseer for the bridge monitor worker.
|
||||
};
|
||||
|
||||
|
||||
AppController& app(); ///< Return a reference to the app controller.
|
||||
|
||||
|
||||
#endif // BRIDGE_GUI_APP_CONTROLLER_H
|
||||
@ -1,177 +0,0 @@
|
||||
# Copyright (c) 2022 Proton AG
|
||||
#
|
||||
# This file is part of Proton Mail Bridge.
|
||||
#
|
||||
# Proton Mail Bridge is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Proton Mail Bridge is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
cmake_minimum_required(VERSION 3.22)
|
||||
set(BRIDGE_REPO_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/../../../..")
|
||||
include(../BridgeSetup.cmake)
|
||||
|
||||
|
||||
#*****************************************************************************************************************************************************
|
||||
# Project
|
||||
#*****************************************************************************************************************************************************
|
||||
|
||||
|
||||
project(bridge-gui LANGUAGES CXX)
|
||||
|
||||
if (NOT DEFINED BRIDGE_APP_FULL_NAME)
|
||||
message(FATAL_ERROR "BRIDGE_APP_FULL_NAME is not defined.")
|
||||
else()
|
||||
message(STATUS "App name is ${BRIDGE_APP_FULL_NAME}")
|
||||
endif()
|
||||
|
||||
if (NOT DEFINED BRIDGE_VENDOR)
|
||||
message(FATAL_ERROR "BRIDGE_VENDOR is not defined.")
|
||||
else()
|
||||
message(STATUS "App vendor is ${BRIDGE_VENDOR}")
|
||||
endif()
|
||||
|
||||
if (NOT DEFINED BRIDGE_APP_VERSION)
|
||||
message(FATAL_ERROR "BRIDGE_APP_VERSION is not defined.")
|
||||
else()
|
||||
message(STATUS "Bridge version is ${BRIDGE_APP_VERSION}")
|
||||
endif()
|
||||
|
||||
if (APPLE) # On macOS, we have some Objective-C++ code in DockIcon to deal with the dock icon.
|
||||
enable_language(OBJC OBJCXX)
|
||||
endif()
|
||||
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
if (APPLE) # We need to link the Cocoa framework for the dock icon.
|
||||
find_library(COCOA_LIBRARY Cocoa REQUIRED)
|
||||
endif()
|
||||
|
||||
|
||||
#*****************************************************************************************************************************************************
|
||||
# Qt
|
||||
#*****************************************************************************************************************************************************
|
||||
|
||||
|
||||
if (NOT DEFINED ENV{QT6DIR})
|
||||
message(FATAL_ERROR "QT6DIR needs to be defined and point to the root of your Qt 6 folder (e.g. /Users/MyName/Qt/6.3.1/clang_64).")
|
||||
endif()
|
||||
|
||||
set(CMAKE_PREFIX_PATH $ENV{QT6DIR} ${CMAKE_PREFIX_PATH})
|
||||
|
||||
# Use CMAKE_INSTALL_PREFIX that is also used internally by CMake
|
||||
if (DEFINED ENV{BRIDGE_INSTALL_PATH})
|
||||
set(CMAKE_INSTALL_PREFIX "$ENV{BRIDGE_INSTALL_PATH}")
|
||||
else(DEFINED ENV{BRIDGE_INSTALL_PATH})
|
||||
message(STATUS "Using Default install path (${CMAKE_INSTALL_PREFIX}), export BRIDGE_INSTALL_PATH to change it.")
|
||||
endif(DEFINED ENV{BRIDGE_INSTALL_PATH})
|
||||
|
||||
if(NOT UNIX)
|
||||
# To change the value of QT_DEPLOY_BIN_DIR, ensure that the project sets CMAKE_INSTALL_BINDIR before the Core package is found.
|
||||
set(CMAKE_INSTALL_BINDIR ".")
|
||||
endif(NOT UNIX)
|
||||
|
||||
find_package(Qt6 COMPONENTS Core Quick Qml QuickControls2 Widgets REQUIRED)
|
||||
qt_standard_project_setup()
|
||||
set(CMAKE_AUTORCC ON)
|
||||
message(STATUS "Using Qt ${Qt6_VERSION}")
|
||||
|
||||
|
||||
#*****************************************************************************************************************************************************
|
||||
# Source files and output
|
||||
#*****************************************************************************************************************************************************
|
||||
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Version.h.in ${CMAKE_CURRENT_SOURCE_DIR}/Version.h)
|
||||
|
||||
if (NOT TARGET bridgepp)
|
||||
add_subdirectory(../bridgepp bridgepp)
|
||||
endif()
|
||||
|
||||
if (APPLE)
|
||||
set(DOCK_ICON_SRC_FILE DockIcon/DockIcon.mm)
|
||||
else()
|
||||
set(DOCK_ICON_SRC_FILE DockIcon/DockIcon.cpp)
|
||||
endif()
|
||||
|
||||
if(UNIX)
|
||||
list(APPEND CMAKE_INSTALL_RPATH "$ORIGIN/lib" )
|
||||
endif(UNIX)
|
||||
|
||||
add_executable(bridge-gui
|
||||
Resources.qrc
|
||||
AppController.cpp AppController.h
|
||||
EventStreamWorker.cpp EventStreamWorker.h
|
||||
main.cpp
|
||||
Pch.h
|
||||
Version.h
|
||||
QMLBackend.cpp QMLBackend.h
|
||||
UserList.cpp UserList.h
|
||||
${DOCK_ICON_SRC_FILE} DockIcon/DockIcon.h
|
||||
)
|
||||
|
||||
if (WIN32) # on Windows, we add a (non-Qt) resource file that contains the application icon and version information.
|
||||
string(TIMESTAMP BRIDGE_BUILD_YEAR "%Y")
|
||||
set(REGEX_NUMBER "[0123456789]") # CMake matches does not support \d.
|
||||
if (${BRIDGE_APP_VERSION} MATCHES "^(${REGEX_NUMBER}+)\\.(${REGEX_NUMBER}+)\\.(${REGEX_NUMBER}+)")
|
||||
set(BRIDGE_APP_VERSION_COMMA "${CMAKE_MATCH_1},${CMAKE_MATCH_2},${CMAKE_MATCH_3},0")
|
||||
else()
|
||||
message(FATAL_ERROR "Could not extract comma-separated version number from ${BRIDGE_APP_VERSION}")
|
||||
endif()
|
||||
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/Resources.rc.in" "${CMAKE_CURRENT_SOURCE_DIR}/Resources.rc")
|
||||
target_sources(bridge-gui PRIVATE Resources.rc)
|
||||
endif()
|
||||
|
||||
target_precompile_headers(bridge-gui PRIVATE Pch.h)
|
||||
target_include_directories(bridge-gui PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
target_link_libraries(bridge-gui
|
||||
Qt6::Widgets
|
||||
Qt6::Core
|
||||
Qt6::Quick
|
||||
Qt6::Qml
|
||||
Qt6::QuickControls2
|
||||
bridgepp
|
||||
)
|
||||
|
||||
if (APPLE)
|
||||
target_link_libraries(bridge-gui ${COCOA_LIBRARY})
|
||||
endif()
|
||||
|
||||
#*****************************************************************************************************************************************************
|
||||
# Deploy
|
||||
#*****************************************************************************************************************************************************
|
||||
set( CMAKE_EXPORT_COMPILE_COMMANDS ON )
|
||||
|
||||
set_target_properties(bridge-gui PROPERTIES
|
||||
WIN32_EXECUTABLE TRUE
|
||||
MACOSX_BUNDLE TRUE)
|
||||
|
||||
install(TARGETS bridge-gui
|
||||
RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}"
|
||||
BUNDLE DESTINATION "${CMAKE_INSTALL_PREFIX}"
|
||||
LIBRARY DESTINATION "${CMAKE_INSTALL_PREFIX}"
|
||||
)
|
||||
|
||||
qt_generate_deploy_app_script(
|
||||
TARGET bridge-gui
|
||||
FILENAME_VARIABLE deploy_script
|
||||
NO_UNSUPPORTED_PLATFORM_ERROR)
|
||||
|
||||
if(UNIX AND NOT APPLE)
|
||||
set(DEPLOY_OS Linux)
|
||||
elseif(APPLE)
|
||||
set(DEPLOY_OS Darwin)
|
||||
else()
|
||||
set(DEPLOY_OS Windows)
|
||||
endif()
|
||||
|
||||
include(Deploy${DEPLOY_OS}.cmake)
|
||||
@ -1,49 +0,0 @@
|
||||
# Copyright (c) 2022 Proton AG
|
||||
#
|
||||
# This file is part of Proton Mail Bridge.
|
||||
#
|
||||
# Proton Mail Bridge is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Proton Mail Bridge is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
cmake_minimum_required(VERSION 3.22)
|
||||
|
||||
#*****************************************************************************************************************************************************
|
||||
# Deploy
|
||||
#*****************************************************************************************************************************************************
|
||||
|
||||
install(SCRIPT ${deploy_script})
|
||||
|
||||
# QML
|
||||
install(DIRECTORY "$ENV{QT6DIR}/qml/Qt"
|
||||
DESTINATION "${CMAKE_INSTALL_PREFIX}/bridge-gui.app/Contents/MacOS")
|
||||
install(DIRECTORY "$ENV{QT6DIR}/qml/QtQml"
|
||||
DESTINATION "${CMAKE_INSTALL_PREFIX}/bridge-gui.app/Contents/MacOS")
|
||||
install(DIRECTORY "$ENV{QT6DIR}/qml/QtQuick"
|
||||
DESTINATION "${CMAKE_INSTALL_PREFIX}/bridge-gui.app/Contents/MacOS")
|
||||
# FRAMEWORKS
|
||||
install(DIRECTORY "$ENV{QT6DIR}/lib/QtQmlWorkerScript.framework"
|
||||
DESTINATION "${CMAKE_INSTALL_PREFIX}/bridge-gui.app/Contents/Frameworks")
|
||||
install(DIRECTORY "$ENV{QT6DIR}/lib/QtQuickControls2Impl.framework"
|
||||
DESTINATION "${CMAKE_INSTALL_PREFIX}/bridge-gui.app/Contents/Frameworks")
|
||||
install(DIRECTORY "$ENV{QT6DIR}/lib/QtQuickLayouts.framework"
|
||||
DESTINATION "${CMAKE_INSTALL_PREFIX}/bridge-gui.app/Contents/Frameworks")
|
||||
install(DIRECTORY "$ENV{QT6DIR}/lib/QtQuickDialogs2.framework"
|
||||
DESTINATION "${CMAKE_INSTALL_PREFIX}/bridge-gui.app/Contents/Frameworks")
|
||||
install(DIRECTORY "$ENV{QT6DIR}/lib/QtQuickDialogs2QuickImpl.framework"
|
||||
DESTINATION "${CMAKE_INSTALL_PREFIX}/bridge-gui.app/Contents/Frameworks")
|
||||
install(DIRECTORY "$ENV{QT6DIR}/lib/QtQuickDialogs2Utils.framework"
|
||||
DESTINATION "${CMAKE_INSTALL_PREFIX}/bridge-gui.app/Contents/Frameworks")
|
||||
# PLUGINS
|
||||
install(FILES "$ENV{QT6DIR}/plugins/imageformats/libqsvg.dylib"
|
||||
DESTINATION "${CMAKE_INSTALL_PREFIX}/bridge-gui.app/Contents/PlugIns/imageformats")
|
||||
|
||||
@ -1,72 +0,0 @@
|
||||
# Copyright (c) 2022 Proton AG
|
||||
#
|
||||
# This file is part of Proton Mail Bridge.
|
||||
#
|
||||
# Proton Mail Bridge is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Proton Mail Bridge is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
cmake_minimum_required(VERSION 3.22)
|
||||
|
||||
#*****************************************************************************************************************************************************
|
||||
# Deploy
|
||||
#*****************************************************************************************************************************************************
|
||||
|
||||
set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_BINDIR}" "${CMAKE_INSTALL_LIBDIR}" "." "../lib")
|
||||
install(DIRECTORY "$ENV{QT6DIR}/qml" "$ENV{QT6DIR}/plugins"
|
||||
DESTINATION "${CMAKE_INSTALL_PREFIX}")
|
||||
|
||||
macro( AppendLib LIB_NAME HINT_PATH)
|
||||
string(TOUPPER ${LIB_NAME} UP_NAME)
|
||||
|
||||
find_library(PATH_${UP_NAME} ${LIB_NAME} HINTS "${HINT_PATH}")
|
||||
|
||||
if( ${PATH_${UP_NAME}} STREQUAL "PATH_${UP_NAME}-NOTFOUND")
|
||||
message(SEND_ERROR "${LIB_NAME} was not found in ${HINT_PATH}")
|
||||
else()
|
||||
get_filename_component(REAL_PATH_${UP_NAME} ${PATH_${UP_NAME}} REALPATH)
|
||||
list(APPEND DEPLOY_LIBS ${PATH_${UP_NAME}})
|
||||
list(APPEND DEPLOY_LIBS ${REAL_PATH_${UP_NAME}})
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
macro( AppendQt6Lib LIB_NAME)
|
||||
AppendLib("${LIB_NAME}" "$ENV{QT6DIR}/lib/")
|
||||
endmacro()
|
||||
|
||||
#Qt6
|
||||
AppendQt6Lib("libQt6QuickControls2.so.6")
|
||||
AppendQt6Lib("libQt6Quick.so.6")
|
||||
AppendQt6Lib("libQt6QmlModels.so.6")
|
||||
AppendQt6Lib("libQt6Qml.so.6")
|
||||
AppendQt6Lib("libQt6Network.so.6")
|
||||
AppendQt6Lib("libQt6OpenGL.so.6")
|
||||
AppendQt6Lib("libQt6Gui.so.6")
|
||||
AppendQt6Lib("libQt6Core.so.6")
|
||||
AppendQt6Lib("libQt6QuickTemplates2.so.6")
|
||||
AppendQt6Lib("libQt6DBus.so.6")
|
||||
AppendQt6Lib("libicui18n.so.56")
|
||||
AppendQt6Lib("libicuuc.so.56")
|
||||
AppendQt6Lib("libicudata.so.56")
|
||||
AppendQt6Lib("libQt6XcbQpa.so.6")
|
||||
AppendQt6Lib("libQt6WaylandClient.so.6")
|
||||
# QML dependencies
|
||||
AppendQt6Lib("libQt6QmlWorkerScript.so.6")
|
||||
AppendQt6Lib("libQt6Widgets.so.6")
|
||||
AppendQt6Lib("libQt6QuickControls2Impl.so.6")
|
||||
AppendQt6Lib("libQt6QuickLayouts.so.6")
|
||||
AppendQt6Lib("libQt6QuickDialogs2.so.6")
|
||||
AppendQt6Lib("libQt6QuickDialogs2QuickImpl.so.6")
|
||||
AppendQt6Lib("libQt6QuickDialogs2Utils.so.6")
|
||||
AppendQt6Lib("libQt6Svg.so.6")
|
||||
|
||||
install(FILES ${DEPLOY_LIBS} DESTINATION "${CMAKE_INSTALL_PREFIX}/lib")
|
||||
@ -1,77 +0,0 @@
|
||||
# Copyright (c) 2022 Proton AG
|
||||
#
|
||||
# This file is part of Proton Mail Bridge.
|
||||
#
|
||||
# Proton Mail Bridge is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Proton Mail Bridge is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
cmake_minimum_required(VERSION 3.22)
|
||||
|
||||
#*****************************************************************************************************************************************************
|
||||
# Deploy
|
||||
#*****************************************************************************************************************************************************
|
||||
|
||||
install(SCRIPT ${deploy_script})
|
||||
|
||||
macro( AppendLib LIB_NAME HINT_PATH)
|
||||
string(TOUPPER ${LIB_NAME} UP_NAME)
|
||||
|
||||
find_file(PATH_${UP_NAME} ${LIB_NAME} HINTS "${HINT_PATH}")
|
||||
|
||||
if( ${PATH_${UP_NAME}} STREQUAL "PATH_${UP_NAME}-NOTFOUND")
|
||||
message(SEND_ERROR "${LIB_NAME} was not found in ${HINT_PATH}")
|
||||
else()
|
||||
list(APPEND DEPLOY_LIBS ${PATH_${UP_NAME}})
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
macro( AppendVCPKGLib LIB_NAME)
|
||||
AppendLib("${LIB_NAME}" "${VCPKG_ROOT}/installed/x64-windows/bin")
|
||||
endmacro()
|
||||
|
||||
cmake_path(CONVERT $ENV{QT6DIR} TO_CMAKE_PATH_LIST QT6DIR)
|
||||
macro( AppendQt6Lib LIB_NAME)
|
||||
AppendLib("${LIB_NAME}" "${QT6DIR}/bin")
|
||||
endmacro()
|
||||
|
||||
# Force plugins to be installed near the exe.
|
||||
install(SCRIPT ${deploy_script})
|
||||
|
||||
# Vcpkg DLLs
|
||||
AppendVCPKGLib("abseil_dll.dll")
|
||||
AppendVCPKGLib("cares.dll")
|
||||
AppendVCPKGLib("libcrypto-3-x64.dll")
|
||||
AppendVCPKGLib("libprotobuf.dll")
|
||||
AppendVCPKGLib("libssl-3-x64.dll")
|
||||
AppendVCPKGLib("re2.dll")
|
||||
AppendVCPKGLib("zlib1.dll")
|
||||
# QML DLLs
|
||||
AppendQt6Lib("Qt6QmlWorkerScript.dll")
|
||||
AppendQt6Lib("Qt6Widgets.dll")
|
||||
AppendQt6Lib("Qt6QuickControls2Impl.dll")
|
||||
AppendQt6Lib("Qt6QuickLayouts.dll")
|
||||
AppendQt6Lib("Qt6QuickDialogs2.dll")
|
||||
AppendQt6Lib("Qt6QuickDialogs2QuickImpl.dll")
|
||||
AppendQt6Lib("Qt6QuickDialogs2Utils.dll")
|
||||
|
||||
install(FILES ${DEPLOY_LIBS} DESTINATION "${CMAKE_INSTALL_PREFIX}")
|
||||
|
||||
# QML PlugIns
|
||||
install(DIRECTORY ${QT6DIR}/qml/Qt/labs/platform DESTINATION "${CMAKE_INSTALL_PREFIX}/Qt/labs/")
|
||||
install(DIRECTORY ${QT6DIR}/qml/QtQml DESTINATION "${CMAKE_INSTALL_PREFIX}")
|
||||
install(DIRECTORY ${QT6DIR}/qml/QtQuick DESTINATION "${CMAKE_INSTALL_PREFIX}")
|
||||
|
||||
# Runtime system libs
|
||||
set(CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_SKIP TRUE)
|
||||
include(InstallRequiredSystemLibraries)
|
||||
install( PROGRAMS ${CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS} DESTINATION ${CMAKE_INSTALL_PREFIX})
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,83 +0,0 @@
|
||||
// Copyright (c) 2022 Proton AG
|
||||
//
|
||||
// This file is part of Proton Mail Bridge.
|
||||
//
|
||||
// Proton Mail Bridge is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Proton Mail Bridge is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
#include "EventStreamWorker.h"
|
||||
#include <bridgepp/GRPC/GRPCClient.h>
|
||||
#include <bridgepp/Exception/Exception.h>
|
||||
#include <bridgepp/Log/Log.h>
|
||||
|
||||
|
||||
using namespace bridgepp;
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] parent The parent object.
|
||||
//****************************************************************************************************************************************************
|
||||
EventStreamReader::EventStreamReader(QObject *parent)
|
||||
: Worker(parent)
|
||||
{
|
||||
connect(this, &EventStreamReader::started, this, &EventStreamReader::onStarted);
|
||||
connect(this, &EventStreamReader::finished, this, &EventStreamReader::onFinished);
|
||||
connect(this, &EventStreamReader::error, &app().log(), &Log::error);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
//
|
||||
//****************************************************************************************************************************************************
|
||||
void EventStreamReader::run()
|
||||
{
|
||||
try
|
||||
{
|
||||
emit started();
|
||||
|
||||
grpc::Status const status = app().grpc().runEventStreamReader();
|
||||
if (!status.ok())
|
||||
throw Exception(QString::fromStdString(status.error_message()));
|
||||
|
||||
emit finished();
|
||||
}
|
||||
catch (Exception const &e)
|
||||
{
|
||||
emit error(e.qwhat());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
//
|
||||
//****************************************************************************************************************************************************
|
||||
void EventStreamReader::onStarted() const
|
||||
{
|
||||
app().log().debug("EventStreamReader started");
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
//
|
||||
//****************************************************************************************************************************************************
|
||||
void EventStreamReader::onFinished() const
|
||||
{
|
||||
app().log().debug("EventStreamReader finished");
|
||||
if (!app().bridgeMonitor())
|
||||
{
|
||||
// no bridge monitor means we are in a debug environment, running in attached mode. Event stream has terminated, so bridge is shutting
|
||||
// down. Because we're in attached mode, bridge-gui will not get notified that bridge is going down, so we shutdown manually here.
|
||||
qApp->exit(EXIT_SUCCESS);
|
||||
}
|
||||
}
|
||||
@ -1,50 +0,0 @@
|
||||
// Copyright (c) 2022 Proton AG
|
||||
//
|
||||
// This file is part of Proton Mail Bridge.
|
||||
//
|
||||
// Proton Mail Bridge is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Proton Mail Bridge is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
#ifndef BRIDGE_GUI_EVENT_STREAM_WORKER_H
|
||||
#define BRIDGE_GUI_EVENT_STREAM_WORKER_H
|
||||
|
||||
|
||||
#include <bridgepp/Worker/Worker.h>
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \brief Stream reader class.
|
||||
//****************************************************************************************************************************************************
|
||||
class EventStreamReader: public bridgepp::Worker
|
||||
{
|
||||
Q_OBJECT
|
||||
public: // member functions
|
||||
explicit EventStreamReader(QObject *parent); ///< Default constructor.
|
||||
EventStreamReader(EventStreamReader const&) = delete; ///< Disabled copy-constructor.
|
||||
EventStreamReader(EventStreamReader&&) = delete; ///< Disabled assignment copy-constructor.
|
||||
~EventStreamReader() override = default; ///< Destructor.
|
||||
EventStreamReader& operator=(EventStreamReader const&) = delete; ///< Disabled assignment operator.
|
||||
EventStreamReader& operator=(EventStreamReader&&) = delete; ///< Disabled move assignment operator.
|
||||
|
||||
public slots:
|
||||
void run() override; ///< Run the reader.
|
||||
void onStarted() const; ///< Slot for the 'started' signal.
|
||||
void onFinished() const; ///< Slot for the 'finished' signal.
|
||||
|
||||
signals:
|
||||
void eventReceived(QString eventString); ///< signal for events.
|
||||
};
|
||||
|
||||
|
||||
#endif //BRIDGE_GUI_EVENT_STREAM_WORKER_H
|
||||
@ -1,416 +0,0 @@
|
||||
// Copyright (c) 2022 Proton AG
|
||||
//
|
||||
// This file is part of Proton Mail Bridge.
|
||||
//
|
||||
// Proton Mail Bridge is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Proton Mail Bridge is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
#include "QMLBackend.h"
|
||||
#include "EventStreamWorker.h"
|
||||
#include "Version.h"
|
||||
#include <bridgepp/GRPC/GRPCClient.h>
|
||||
#include <bridgepp/Exception/Exception.h>
|
||||
#include <bridgepp/Worker/Overseer.h>
|
||||
|
||||
|
||||
using namespace bridgepp;
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
//
|
||||
//****************************************************************************************************************************************************
|
||||
QMLBackend::QMLBackend()
|
||||
: QObject()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
//
|
||||
//****************************************************************************************************************************************************
|
||||
void QMLBackend::init()
|
||||
{
|
||||
users_ = new UserList(this);
|
||||
|
||||
app().grpc().setLog(&app().log());
|
||||
this->connectGrpcEvents();
|
||||
|
||||
QString error;
|
||||
if (app().grpc().connectToServer(error))
|
||||
app().log().info("Connected to backend via gRPC service.");
|
||||
else
|
||||
throw Exception(QString("Cannot connectToServer to go backend via gRPC: %1").arg(error));
|
||||
|
||||
QString bridgeVer;
|
||||
app().grpc().version(bridgeVer);
|
||||
if (bridgeVer != PROJECT_VER)
|
||||
throw Exception(QString("Version Mismatched from Bridge (%1) and Bridge-GUI (%2)").arg(bridgeVer, PROJECT_VER));
|
||||
|
||||
eventStreamOverseer_ = std::make_unique<Overseer>(new EventStreamReader(nullptr), nullptr);
|
||||
eventStreamOverseer_->startWorker(true);
|
||||
|
||||
connect(&app().log(), &Log::entryAdded, [&](Log::Level level, QString const& message) {
|
||||
app().grpc().addLogEntry(level, "frontend/bridge-gui", message);
|
||||
});
|
||||
|
||||
// Grab from bridge the value that will not change during the execution of this app (or that will only change locally
|
||||
app().grpc().showSplashScreen(showSplashScreen_);
|
||||
app().grpc().goos(goos_);
|
||||
app().grpc().logsPath(logsPath_);
|
||||
app().grpc().licensePath(licensePath_);
|
||||
|
||||
this->retrieveUserList();
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param timeoutMs The timeout after which the function should return false if the event stream reader is not finished. if -1 one, the function
|
||||
/// never times out.
|
||||
/// \return false if and only if the timeout delay was reached.
|
||||
//****************************************************************************************************************************************************
|
||||
bool QMLBackend::waitForEventStreamReaderToFinish(qint32 timeoutMs)
|
||||
{
|
||||
return eventStreamOverseer_->wait(timeoutMs);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
//
|
||||
//****************************************************************************************************************************************************
|
||||
void QMLBackend::connectGrpcEvents()
|
||||
{
|
||||
GRPCClient *client = &app().grpc();
|
||||
|
||||
// app events
|
||||
connect(client, &GRPCClient::internetStatus, this, [&](bool isOn) { if (isOn) emit internetOn(); else emit internetOff(); });
|
||||
connect(client, &GRPCClient::toggleAutostartFinished, this, &QMLBackend::toggleAutostartFinished);
|
||||
connect(client, &GRPCClient::resetFinished, this, &QMLBackend::onResetFinished);
|
||||
connect(client, &GRPCClient::reportBugFinished, this, &QMLBackend::reportBugFinished);
|
||||
connect(client, &GRPCClient::reportBugSuccess, this, &QMLBackend::bugReportSendSuccess);
|
||||
connect(client, &GRPCClient::reportBugError, this, &QMLBackend::bugReportSendError);
|
||||
connect(client, &GRPCClient::showMainWindow, this, &QMLBackend::showMainWindow);
|
||||
|
||||
// cache events
|
||||
connect(client, &GRPCClient::isCacheOnDiskEnabledChanged, this, &QMLBackend::isDiskCacheEnabledChanged);
|
||||
connect(client, &GRPCClient::diskCachePathChanged, this, &QMLBackend::diskCachePathChanged);
|
||||
connect(client, &GRPCClient::cacheUnavailable, this, &QMLBackend::cacheUnavailable); // _ func() `signal:"cacheUnavailable"`
|
||||
connect(client, &GRPCClient::cacheCantMove, this, &QMLBackend::cacheCantMove);
|
||||
connect(client, &GRPCClient::diskFull, this, &QMLBackend::diskFull);
|
||||
connect(client, &GRPCClient::cacheLocationChangeSuccess, this, &QMLBackend::cacheLocationChangeSuccess);
|
||||
connect(client, &GRPCClient::changeLocalCacheFinished, this, &QMLBackend::onChangeLocalCacheFinished);
|
||||
|
||||
// login events
|
||||
connect(client, &GRPCClient::loginUsernamePasswordError, this, &QMLBackend::loginUsernamePasswordError);
|
||||
connect(client, &GRPCClient::loginFreeUserError, this, &QMLBackend::loginFreeUserError);
|
||||
connect(client, &GRPCClient::loginConnectionError, this, &QMLBackend::loginConnectionError);
|
||||
connect(client, &GRPCClient::login2FARequested, this, &QMLBackend::login2FARequested);
|
||||
connect(client, &GRPCClient::login2FAError, this, &QMLBackend::login2FAError);
|
||||
connect(client, &GRPCClient::login2FAErrorAbort, this, &QMLBackend::login2FAErrorAbort);
|
||||
connect(client, &GRPCClient::login2PasswordRequested, this, &QMLBackend::login2PasswordRequested);
|
||||
connect(client, &GRPCClient::login2PasswordError, this, &QMLBackend::login2PasswordError);
|
||||
connect(client, &GRPCClient::login2PasswordErrorAbort, this, &QMLBackend::login2PasswordErrorAbort);
|
||||
connect(client, &GRPCClient::loginFinished, this, [&](QString const &userID) {
|
||||
this->retrieveUserList();
|
||||
qint32 const index = users_->rowOfUserID(userID); emit loginFinished(index); });
|
||||
connect(client, &GRPCClient::loginAlreadyLoggedIn, this, [&](QString const &userID) {
|
||||
this->retrieveUserList();
|
||||
qint32 const index = users_->rowOfUserID(userID); emit loginAlreadyLoggedIn(index); });
|
||||
|
||||
// update events
|
||||
connect(client, &GRPCClient::updateManualError, this, &QMLBackend::updateManualError);
|
||||
connect(client, &GRPCClient::updateForceError, this, &QMLBackend::updateForceError);
|
||||
connect(client, &GRPCClient::updateSilentError, this, &QMLBackend::updateSilentError);
|
||||
connect(client, &GRPCClient::updateManualReady, this, &QMLBackend::updateManualReady);
|
||||
connect(client, &GRPCClient::updateManualRestartNeeded, this, &QMLBackend::updateManualRestartNeeded);
|
||||
connect(client, &GRPCClient::updateForce, this, &QMLBackend::updateForce);
|
||||
connect(client, &GRPCClient::updateSilentRestartNeeded, this, &QMLBackend::updateSilentRestartNeeded);
|
||||
connect(client, &GRPCClient::updateIsLatestVersion, this, &QMLBackend::updateIsLatestVersion);
|
||||
connect(client, &GRPCClient::checkUpdatesFinished, this, &QMLBackend::checkUpdatesFinished);
|
||||
connect(client, &GRPCClient::updateVersionChanged, this, &QMLBackend::onVersionChanged);
|
||||
|
||||
// mail settings events
|
||||
connect(client, &GRPCClient::portIssueIMAP, this, &QMLBackend::portIssueIMAP);
|
||||
connect(client, &GRPCClient::portIssueSMTP, this, &QMLBackend::portIssueSMTP);
|
||||
connect(client, &GRPCClient::toggleUseSSLFinished, this, &QMLBackend::toggleUseSSLFinished);
|
||||
connect(client, &GRPCClient::changePortFinished, this, &QMLBackend::changePortFinished);
|
||||
|
||||
// keychain events
|
||||
connect(client, &GRPCClient::changeKeychainFinished, this, &QMLBackend::changeKeychainFinished);
|
||||
connect(client, &GRPCClient::hasNoKeychain, this, &QMLBackend::notifyHasNoKeychain);
|
||||
connect(client, &GRPCClient::rebuildKeychain, this, &QMLBackend::notifyRebuildKeychain);
|
||||
|
||||
// mail events
|
||||
connect(client, &GRPCClient::noActiveKeyForRecipient, this, &QMLBackend::noActiveKeyForRecipient);
|
||||
connect(client, &GRPCClient::addressChanged, this, &QMLBackend::addressChanged);
|
||||
connect(client, &GRPCClient::addressChangedLogout, this, &QMLBackend::addressChangedLogout);
|
||||
connect(client, &GRPCClient::apiCertIssue, this, &QMLBackend::apiCertIssue);
|
||||
|
||||
// user events
|
||||
connect(client, &GRPCClient::userDisconnected, this, &QMLBackend::userDisconnected);
|
||||
users_->connectGRPCEvents();
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
//
|
||||
//****************************************************************************************************************************************************
|
||||
void QMLBackend::retrieveUserList()
|
||||
{
|
||||
QList<SPUser> newUsers;
|
||||
app().grpc().getUserList(newUsers);
|
||||
|
||||
// As we want to use shared pointers here, we do not want to use the Qt ownership system, so we set parent to nil.
|
||||
// But: From https://doc.qt.io/qt-5/qtqml-cppintegration-data.html:
|
||||
// " When data is transferred from C++ to QML, the ownership of the data always remains with C++. The exception to this rule
|
||||
// is when a QObject is returned from an explicit C++ method call: in this case, the QML engine assumes ownership of the object. "
|
||||
// This is the case here, so we explicitly indicate that the object is owned by C++.
|
||||
for (SPUser const& user: newUsers)
|
||||
|
||||
for (qsizetype i = 0; i < newUsers.size(); ++i)
|
||||
{
|
||||
SPUser newUser = newUsers[i];
|
||||
SPUser existingUser = users_->getUserWithID(newUser->id());
|
||||
if (!existingUser)
|
||||
{
|
||||
// The user is new. We indicate to QML that it is managed by the C++ backend.
|
||||
QQmlEngine::setObjectOwnership(user.get(), QQmlEngine::CppOwnership);
|
||||
continue;
|
||||
}
|
||||
|
||||
// The user is already listed. QML code may have a pointer because of an ongoing process (for instance in the SetupGuide),
|
||||
// As a consequence we do not want to replace this existing user, but we want to update it.
|
||||
existingUser->update(*newUser);
|
||||
newUsers[i] = existingUser;
|
||||
}
|
||||
|
||||
users_->reset(newUsers);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
//
|
||||
//****************************************************************************************************************************************************
|
||||
QPoint QMLBackend::getCursorPos()
|
||||
{
|
||||
return QCursor::pos();
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
//
|
||||
//****************************************************************************************************************************************************
|
||||
bool QMLBackend::isPortFree(int port)
|
||||
{
|
||||
bool isFree = false;
|
||||
app().grpc().isPortFree(port, isFree);
|
||||
return isFree;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
//
|
||||
//****************************************************************************************************************************************************
|
||||
void QMLBackend::guiReady()
|
||||
{
|
||||
app().grpc().guiReady();
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
//
|
||||
//****************************************************************************************************************************************************
|
||||
void QMLBackend::quit()
|
||||
{
|
||||
app().grpc().quit();
|
||||
qApp->exit(0);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
//
|
||||
//****************************************************************************************************************************************************
|
||||
void QMLBackend::restart()
|
||||
{
|
||||
app().grpc().restart();
|
||||
app().grpc().quit();
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] launcher The path to the launcher.
|
||||
//****************************************************************************************************************************************************
|
||||
void QMLBackend::forceLauncher(QString launcher)
|
||||
{
|
||||
app().grpc().forceLauncher(launcher);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] active Should we activate autostart.
|
||||
//****************************************************************************************************************************************************
|
||||
void QMLBackend::toggleAutostart(bool active)
|
||||
{
|
||||
app().grpc().setIsAutostartOn(active);
|
||||
emit isAutostartOnChanged(this->isAutostartOn());
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] active The new state for the beta enabled property.
|
||||
//****************************************************************************************************************************************************
|
||||
void QMLBackend::toggleBeta(bool active)
|
||||
{
|
||||
app().grpc().setIsBetaEnabled(active);
|
||||
emit isBetaEnabledChanged(this->isBetaEnabled());
|
||||
}
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] active The new state for the All Mail visibility property.
|
||||
//****************************************************************************************************************************************************
|
||||
void QMLBackend::changeIsAllMailVisible(bool isVisible)
|
||||
{
|
||||
app().grpc().setIsAllMailVisible(isVisible);
|
||||
emit isAllMailVisibleChanged(this->isAllMailVisible());
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] scheme the scheme name
|
||||
//****************************************************************************************************************************************************
|
||||
void QMLBackend::changeColorScheme(QString const &scheme)
|
||||
{
|
||||
app().grpc().setColorSchemeName(scheme);
|
||||
emit colorSchemeNameChanged(this->colorSchemeName());
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] makeItActive Should SSL for SMTP be enabled.
|
||||
//****************************************************************************************************************************************************
|
||||
void QMLBackend::toggleUseSSLforSMTP(bool makeItActive)
|
||||
{
|
||||
// if call succeed, app will restart. No need to emit a value change signal, because it will trigger a read-back via gRPC that will fail.
|
||||
emit hideMainWindow();
|
||||
app().grpc().setUseSSLForSMTP(makeItActive);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] imapPort The IMAP port.
|
||||
/// \param[in] smtpPort The SMTP port.
|
||||
//****************************************************************************************************************************************************
|
||||
void QMLBackend::changePorts(int imapPort, int smtpPort)
|
||||
{
|
||||
// if call succeed, app will restart. No need to emit a value change signal, because it will trigger a read-back via gRPC that will fail.
|
||||
emit hideMainWindow();
|
||||
app().grpc().changePorts(imapPort, smtpPort);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] enable Is cache enabled?
|
||||
/// \param[in] path The path of the cache.
|
||||
//****************************************************************************************************************************************************
|
||||
void QMLBackend::changeLocalCache(bool enable, QUrl const &path)
|
||||
{
|
||||
app().grpc().changeLocalCache(enable, path);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] active Should DoH be active.
|
||||
//****************************************************************************************************************************************************
|
||||
void QMLBackend::toggleDoH(bool active)
|
||||
{
|
||||
if (app().grpc().setIsDoHEnabled(active).ok())
|
||||
emit isDoHEnabledChanged(active);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] keychain The new keychain.
|
||||
//****************************************************************************************************************************************************
|
||||
void QMLBackend::changeKeychain(QString const &keychain)
|
||||
{
|
||||
if (app().grpc().setCurrentKeychain(keychain).ok())
|
||||
emit currentKeychainChanged(keychain);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] active Should automatic update be turned on.
|
||||
//****************************************************************************************************************************************************
|
||||
void QMLBackend::toggleAutomaticUpdate(bool active)
|
||||
{
|
||||
if (app().grpc().setIsAutomaticUpdateOn(active).ok())
|
||||
emit isAutomaticUpdateOnChanged(active);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
//
|
||||
//****************************************************************************************************************************************************
|
||||
void QMLBackend::checkUpdates()
|
||||
{
|
||||
app().grpc().checkUpdate();
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
//
|
||||
//****************************************************************************************************************************************************
|
||||
void QMLBackend::installUpdate()
|
||||
{
|
||||
app().grpc().installUpdate();
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
//
|
||||
//****************************************************************************************************************************************************
|
||||
void QMLBackend::triggerReset()
|
||||
{
|
||||
app().grpc().triggerReset();
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
//
|
||||
//****************************************************************************************************************************************************
|
||||
void QMLBackend::onResetFinished()
|
||||
{
|
||||
emit resetFinished();
|
||||
this->restart();
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
// onVersionChanged update dynamic link related to version
|
||||
//****************************************************************************************************************************************************
|
||||
void QMLBackend::onVersionChanged()
|
||||
{
|
||||
emit releaseNotesLinkChanged(releaseNotesLink());
|
||||
emit landingPageLinkChanged(landingPageLink());
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
///
|
||||
//****************************************************************************************************************************************************
|
||||
void QMLBackend::onChangeLocalCacheFinished(bool willRestart)
|
||||
{
|
||||
if (willRestart)
|
||||
emit hideMainWindow();
|
||||
emit changeLocalCacheFinished();
|
||||
}
|
||||
@ -1,238 +0,0 @@
|
||||
// Copyright (c) 2022 Proton AG
|
||||
//
|
||||
// This file is part of Proton Mail Bridge.
|
||||
//
|
||||
// Proton Mail Bridge is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Proton Mail Bridge is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
#ifndef BRIDGE_GUI_QML_BACKEND_H
|
||||
#define BRIDGE_GUI_QML_BACKEND_H
|
||||
|
||||
|
||||
#include "DockIcon/DockIcon.h"
|
||||
#include "Version.h"
|
||||
#include "UserList.h"
|
||||
#include <bridgepp/GRPC/GRPCClient.h>
|
||||
#include <bridgepp/GRPC/GRPCUtils.h>
|
||||
#include <bridgepp/Worker/Overseer.h>
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \brief Bridge C++ backend class.
|
||||
//****************************************************************************************************************************************************
|
||||
class QMLBackend: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public: // member functions.
|
||||
QMLBackend(); ///< Default constructor.
|
||||
QMLBackend(QMLBackend const &) = delete; ///< Disabled copy-constructor.
|
||||
QMLBackend(QMLBackend &&) = delete; ///< Disabled assignment copy-constructor.
|
||||
~QMLBackend() override = default; ///< Destructor.
|
||||
QMLBackend &operator=(QMLBackend const &) = delete; ///< Disabled assignment operator.
|
||||
QMLBackend &operator=(QMLBackend &&) = delete; ///< Disabled move assignment operator.
|
||||
void init(); ///< Initialize the backend.
|
||||
bool waitForEventStreamReaderToFinish(qint32 timeoutMs); ///< Wait for the event stream reader to finish.
|
||||
|
||||
// invokable methods can be called from QML. They generally return a value, which slots cannot do.
|
||||
Q_INVOKABLE static QPoint getCursorPos(); // _ func() *core.QPoint `slot:"getCursorPos"`
|
||||
Q_INVOKABLE static bool isPortFree(int port); // _ func(port int) bool `slot:"isPortFree"`
|
||||
|
||||
public: // Qt/QML properties. Note that the NOTIFY-er signal is required even for read-only properties (QML warning otherwise)
|
||||
Q_PROPERTY(bool showOnStartup READ showOnStartup NOTIFY showOnStartupChanged) // _ bool `property:showOnStartup`
|
||||
Q_PROPERTY(bool showSplashScreen READ showSplashScreen WRITE setShowSplashScreen NOTIFY showSplashScreenChanged) // _ bool `property:showSplashScreen`
|
||||
Q_PROPERTY(QString goos READ goos NOTIFY goosChanged) // _ string `property:"goos"`
|
||||
Q_PROPERTY(QUrl logsPath READ logsPath NOTIFY logsPathChanged) // _ core.QUrl `property:"logsPath"`
|
||||
Q_PROPERTY(QUrl licensePath READ licensePath NOTIFY licensePathChanged) // _ core.QUrl `property:"licensePath"`
|
||||
Q_PROPERTY(QUrl releaseNotesLink READ releaseNotesLink NOTIFY releaseNotesLinkChanged) // _ core.QUrl `property:"releaseNotesLink"`
|
||||
Q_PROPERTY(QUrl dependencyLicensesLink READ dependencyLicensesLink NOTIFY dependencyLicensesLinkChanged) // _ core.QUrl `property:"dependencyLicensesLink"`
|
||||
Q_PROPERTY(QUrl landingPageLink READ landingPageLink NOTIFY landingPageLinkChanged) // _ core.QUrl `property:"landingPageLink"`
|
||||
Q_PROPERTY(QString appname READ appname NOTIFY appnameChanged) // _ string `property:"version"`
|
||||
Q_PROPERTY(QString vendor READ vendor NOTIFY vendorChanged) // _ string `property:"version"`
|
||||
Q_PROPERTY(QString version READ version NOTIFY versionChanged) // _ string `property:"version"`
|
||||
Q_PROPERTY(QString hostname READ hostname NOTIFY hostnameChanged) // _ string `property:"hostname"`
|
||||
Q_PROPERTY(bool isAutostartOn READ isAutostartOn NOTIFY isAutostartOnChanged) // _ bool `property:"isAutostartOn"`
|
||||
Q_PROPERTY(bool isBetaEnabled READ isBetaEnabled NOTIFY isBetaEnabledChanged) // _ bool `property:"isBetaEnabled"`
|
||||
Q_PROPERTY(bool isAllMailVisible READ isAllMailVisible NOTIFY isAllMailVisibleChanged) // _ bool `property:"isAllMailVisible"`
|
||||
Q_PROPERTY(QString colorSchemeName READ colorSchemeName NOTIFY colorSchemeNameChanged) // _ string `property:"colorSchemeName"`
|
||||
Q_PROPERTY(bool isDiskCacheEnabled READ isDiskCacheEnabled NOTIFY isDiskCacheEnabledChanged) // _ bool `property:"isDiskCacheEnabled"`
|
||||
Q_PROPERTY(QUrl diskCachePath READ diskCachePath NOTIFY diskCachePathChanged) // _ core.QUrl `property:"diskCachePath"`
|
||||
Q_PROPERTY(bool useSSLforSMTP READ useSSLForSMTP NOTIFY useSSLforSMTPChanged) // _ bool `property:"useSSLforSMTP"`
|
||||
Q_PROPERTY(int portIMAP READ portIMAP NOTIFY portIMAPChanged) // _ int `property:"portIMAP"`
|
||||
Q_PROPERTY(int portSMTP READ portSMTP NOTIFY portSMTPChanged) // _ int `property:"portSMTP"`
|
||||
Q_PROPERTY(bool isDoHEnabled READ isDoHEnabled NOTIFY isDoHEnabledChanged) // _ bool `property:"isDoHEnabled"`
|
||||
Q_PROPERTY(bool isFirstGUIStart READ isFirstGUIStart) // _ bool `property:"isFirstGUIStart"`
|
||||
Q_PROPERTY(bool isAutomaticUpdateOn READ isAutomaticUpdateOn NOTIFY isAutomaticUpdateOnChanged) // _ bool `property:"isAutomaticUpdateOn"`
|
||||
Q_PROPERTY(QString currentEmailClient READ currentEmailClient NOTIFY currentEmailClientChanged) // _ string `property:"currentEmailClient"`
|
||||
Q_PROPERTY(QStringList availableKeychain READ availableKeychain NOTIFY availableKeychainChanged) // _ []string `property:"availableKeychain"`
|
||||
Q_PROPERTY(QString currentKeychain READ currentKeychain NOTIFY currentKeychainChanged) // _ string `property:"currentKeychain"`
|
||||
Q_PROPERTY(UserList* users MEMBER users_ NOTIFY usersChanged)
|
||||
Q_PROPERTY(bool dockIconVisible READ dockIconVisible WRITE setDockIconVisible NOTIFY dockIconVisibleChanged) // _ bool `property:dockIconVisible`
|
||||
|
||||
// Qt Property system setters & getters.
|
||||
bool showOnStartup() const { bool v = false; app().grpc().showOnStartup(v); return v; };
|
||||
bool showSplashScreen() const { return showSplashScreen_; };
|
||||
void setShowSplashScreen(bool show) { if (show != showSplashScreen_) { showSplashScreen_ = show; emit showSplashScreenChanged(show); } }
|
||||
QString goos() { return goos_; }
|
||||
QUrl logsPath() const { return logsPath_; }
|
||||
QUrl licensePath() const { return licensePath_; }
|
||||
QUrl releaseNotesLink() const { QUrl link; app().grpc().releaseNotesPageLink(link); return link; }
|
||||
QUrl dependencyLicensesLink() const { QUrl link; app().grpc().dependencyLicensesLink(link); return link; }
|
||||
QUrl landingPageLink() const { QUrl link; app().grpc().landingPageLink(link); return link; }
|
||||
QString appname() const { return QString(PROJECT_FULL_NAME); }
|
||||
QString vendor() const { return QString(PROJECT_VENDOR); }
|
||||
QString version() const { QString version; app().grpc().version(version); return version; }
|
||||
QString hostname() const { QString hostname; app().grpc().hostname(hostname); return hostname; }
|
||||
bool isAutostartOn() const { bool v; app().grpc().isAutostartOn(v); return v; };
|
||||
bool isBetaEnabled() const { bool v; app().grpc().isBetaEnabled(v); return v; }
|
||||
bool isAllMailVisible() const { bool v; app().grpc().isAllMailVisible(v); return v; }
|
||||
QString colorSchemeName() const { QString name; app().grpc().colorSchemeName(name); return name; }
|
||||
bool isDiskCacheEnabled() const { bool enabled; app().grpc().isCacheOnDiskEnabled(enabled); return enabled;}
|
||||
QUrl diskCachePath() const { QUrl path; app().grpc().diskCachePath(path); return path; }
|
||||
bool useSSLForSMTP() const{ bool useSSL; app().grpc().useSSLForSMTP(useSSL); return useSSL; }
|
||||
int portIMAP() const { int port; app().grpc().portIMAP(port); return port; }
|
||||
int portSMTP() const { int port; app().grpc().portSMTP(port); return port; }
|
||||
bool isDoHEnabled() const { bool isEnabled; app().grpc().isDoHEnabled(isEnabled); return isEnabled;}
|
||||
bool isFirstGUIStart() const { bool v; app().grpc().isFirstGUIStart(v); return v; };
|
||||
bool isAutomaticUpdateOn() const { bool isOn = false; app().grpc().isAutomaticUpdateOn(isOn); return isOn; }
|
||||
QString currentEmailClient() { QString client; app().grpc().currentEmailClient(client); return client;}
|
||||
QStringList availableKeychain() const { QStringList keychains; app().grpc().availableKeychains(keychains); return keychains; }
|
||||
QString currentKeychain() const { QString keychain; app().grpc().currentKeychain(keychain); return keychain; }
|
||||
bool dockIconVisible() const { return getDockIconVisibleState(); };
|
||||
void setDockIconVisible(bool visible) { setDockIconVisibleState(visible); emit dockIconVisibleChanged(visible); }
|
||||
|
||||
signals: // Signal used by the Qt property system. Many of them are unused but required to avoir warning from the QML engine.
|
||||
void showSplashScreenChanged(bool value);
|
||||
void showOnStartupChanged(bool value);
|
||||
void goosChanged(QString const &value);
|
||||
void isDiskCacheEnabledChanged(bool value);
|
||||
void diskCachePathChanged(QUrl const &url);
|
||||
void useSSLforSMTPChanged(bool value);
|
||||
void isAutomaticUpdateOnChanged(bool value);
|
||||
void isBetaEnabledChanged(bool value);
|
||||
void isAllMailVisibleChanged(bool value);
|
||||
void colorSchemeNameChanged(QString const &scheme);
|
||||
void isDoHEnabledChanged(bool value);
|
||||
void logsPathChanged(QUrl const &path);
|
||||
void licensePathChanged(QUrl const &path);
|
||||
void releaseNotesLinkChanged(QUrl const &link);
|
||||
void dependencyLicensesLinkChanged(QUrl const &link);
|
||||
void landingPageLinkChanged(QUrl const &link);
|
||||
void appnameChanged(QString const &appname);
|
||||
void vendorChanged(QString const &vendor);
|
||||
void versionChanged(QString const &version);
|
||||
void currentEmailClientChanged(QString const &email);
|
||||
void currentKeychainChanged(QString const &keychain);
|
||||
void availableKeychainChanged(QStringList const &keychains);
|
||||
void hostnameChanged(QString const &hostname);
|
||||
void isAutostartOnChanged(bool value);
|
||||
void portIMAPChanged(int port);
|
||||
void portSMTPChanged(int port);
|
||||
void usersChanged(UserList* users);
|
||||
void dockIconVisibleChanged(bool value);
|
||||
|
||||
public slots: // slot for signals received from QML -> To be forwarded to Bridge via RPC Client calls.
|
||||
void toggleAutostart(bool active); // _ func(makeItActive bool) `slot:"toggleAutostart"`
|
||||
void toggleBeta(bool active); // _ func(makeItActive bool) `slot:"toggleBeta"`
|
||||
void changeIsAllMailVisible(bool isVisible); // _ func(isVisible bool) `slot:"changeIsAllMailVisible"`
|
||||
void changeColorScheme(QString const &scheme); // _ func(string) `slot:"changeColorScheme"`
|
||||
void changeLocalCache(bool enable, QUrl const& path); // _ func(enableDiskCache bool, diskCachePath core.QUrl) `slot:"changeLocalCache"`
|
||||
void login(QString const& username, QString const& password) { app().grpc().login(username, password);} // _ func(username, password string) `slot:"login"`
|
||||
void login2FA(QString const& username, QString const& code) { app().grpc().login2FA(username, code);} // _ func(username, code string) `slot:"login2FA"`
|
||||
void login2Password(QString const& username, QString const& password) { app().grpc().login2Passwords(username, password);} // _ func(username, password string) `slot:"login2Password"`
|
||||
void loginAbort(QString const& username){ app().grpc().loginAbort(username);} // _ func(username string) `slot:"loginAbort"`
|
||||
void toggleUseSSLforSMTP(bool makeItActive); // _ func(makeItActive bool) `slot:"toggleUseSSLforSMTP"`
|
||||
void changePorts(int imapPort, int smtpPort); // _ func(imapPort, smtpPort int) `slot:"changePorts"`
|
||||
void toggleDoH(bool active); // _ func(makeItActive bool) `slot:"toggleDoH"`
|
||||
void toggleAutomaticUpdate(bool makeItActive); // _ func(makeItActive bool) `slot:"toggleAutomaticUpdate"`
|
||||
void updateCurrentMailClient() { emit currentEmailClientChanged(currentEmailClient()); } // _ func() `slot:"updateCurrentMailClient"`
|
||||
void changeKeychain(QString const &keychain); // _ func(keychain string) `slot:"changeKeychain"`
|
||||
void guiReady(); // _ func() `slot:"guiReady"`
|
||||
void quit(); // _ func() `slot:"quit"`
|
||||
void restart(); // _ func() `slot:"restart"`
|
||||
void forceLauncher(QString launcher); // _ func() `slot:"forceLauncher"`
|
||||
void checkUpdates(); // _ func() `slot:"checkUpdates"`
|
||||
void installUpdate(); // _ func() `slot:"installUpdate"`
|
||||
void triggerReset(); // _ func() `slot:"triggerReset"`
|
||||
void reportBug(QString const &description, QString const& address, QString const &emailClient, bool includeLogs) {
|
||||
app().grpc().reportBug(description, address, emailClient, includeLogs); } // _ func(description, address, emailClient string, includeLogs bool) `slot:"reportBug"`
|
||||
void onResetFinished(); // _ func() `slot:"onResetFinished"`
|
||||
void onVersionChanged(); // _ func() `slot:"onVersionChanged"`
|
||||
void onChangeLocalCacheFinished(bool willRestart);
|
||||
|
||||
signals: // Signals received from the Go backend, to be forwarded to QML
|
||||
void toggleAutostartFinished(); // _ func() `signal:"toggleAutostartFinished"`
|
||||
void cacheUnavailable(); // _ func() `signal:"cacheUnavailable"`
|
||||
void cacheCantMove(); // _ func() `signal:"cacheCantMove"`
|
||||
void cacheLocationChangeSuccess(); // _ func() `signal:"cacheLocationChangeSuccess"`
|
||||
void diskFull(); // _ func() `signal:"diskFull"`
|
||||
void changeLocalCacheFinished(); // _ func() `signal:"changeLocalCacheFinished"`
|
||||
void loginUsernamePasswordError(QString const &errorMsg); // _ func(errorMsg string) `signal:"loginUsernamePasswordError"`
|
||||
void loginFreeUserError(); // _ func() `signal:"loginFreeUserError"`
|
||||
void loginConnectionError(QString const &errorMsg); // _ func(errorMsg string) `signal:"loginConnectionError"`
|
||||
void login2FARequested(QString const &username); // _ func(username string) `signal:"login2FARequested"`
|
||||
void login2FAError(QString const& errorMsg); // _ func(errorMsg string) `signal:"login2FAError"`
|
||||
void login2FAErrorAbort(QString const& errorMsg); // _ func(errorMsg string) `signal:"login2FAErrorAbort"`
|
||||
void login2PasswordRequested(); // _ func() `signal:"login2PasswordRequested"`
|
||||
void login2PasswordError(QString const& errorMsg); // _ func(errorMsg string) `signal:"login2PasswordError"`
|
||||
void login2PasswordErrorAbort(QString const& errorMsg); // _ func(errorMsg string) `signal:"login2PasswordErrorAbort"`
|
||||
void loginFinished(int index); // _ func(index int) `signal:"loginFinished"`
|
||||
void loginAlreadyLoggedIn(int index); // _ func(index int) `signal:"loginAlreadyLoggedIn"`
|
||||
void updateManualReady(QString const& version); // _ func(version string) `signal:"updateManualReady"`
|
||||
void updateManualRestartNeeded(); // _ func() `signal:"updateManualRestartNeeded"`
|
||||
void updateManualError(); // _ func() `signal:"updateManualError"`
|
||||
void updateForce(QString const& version); // _ func(version string) `signal:"updateForce"`
|
||||
void updateForceError(); // _ func() `signal:"updateForceError"`
|
||||
void updateSilentRestartNeeded(); // _ func() `signal:"updateSilentRestartNeeded"`
|
||||
void updateSilentError(); // _ func() `signal:"updateSilentError"`
|
||||
void updateIsLatestVersion(); // _ func() `signal:"updateIsLatestVersion"`
|
||||
void checkUpdatesFinished(); // _ func() `signal:"checkUpdatesFinished"`
|
||||
void toggleUseSSLFinished(); // _ func() `signal:"toggleUseSSLFinished"`
|
||||
void changePortFinished(); // _ func() `signal:"changePortFinished"`
|
||||
void portIssueIMAP(); // _ func() `signal:"portIssueIMAP"`
|
||||
void portIssueSMTP(); // _ func() `signal:"portIssueSMTP"`
|
||||
void changeKeychainFinished(); // _ func() `signal:"changeKeychainFinished"`
|
||||
void notifyHasNoKeychain(); // _ func() `signal:"notifyHasNoKeychain"`
|
||||
void notifyRebuildKeychain(); // _ func() `signal:"notifyRebuildKeychain"`
|
||||
void noActiveKeyForRecipient(QString const& email); // _ func(email string) `signal:noActiveKeyForRecipient`
|
||||
void addressChanged(QString const& address); // _ func(address string) `signal:addressChanged`
|
||||
void addressChangedLogout(QString const& address); // _ func(address string) `signal:addressChangedLogout`
|
||||
void apiCertIssue(); // _ func() `signal:apiCertIssue`
|
||||
void userDisconnected(QString const& username); // _ func(username string) `signal:userDisconnected`
|
||||
void internetOff(); // _ func() `signal:"internetOff"`
|
||||
void internetOn(); // _ func() `signal:"internetOn"`
|
||||
void resetFinished(); // _ func() `signal:"resetFinished"`
|
||||
void reportBugFinished(); // _ func() `signal:"reportBugFinished"`
|
||||
void bugReportSendSuccess(); // _ func() `signal:"bugReportSendSuccess"`
|
||||
void bugReportSendError(); // _ func() `signal:"bugReportSendError"`
|
||||
void showMainWindow(); // _ func() `signal:showMainWindow`
|
||||
void hideMainWindow();
|
||||
|
||||
private: // member functions
|
||||
void retrieveUserList(); ///< Retrieve the list of users via gRPC.
|
||||
void connectGrpcEvents(); ///< Connect gRPC that need to be forwarded to QML via backend signals
|
||||
|
||||
private: // data members
|
||||
UserList* users_ { nullptr }; ///< The user list. Owned by backend.
|
||||
std::unique_ptr<bridgepp::Overseer> eventStreamOverseer_; ///< The event stream overseer.
|
||||
bool showSplashScreen_ { false }; ///< The cached version of show splash screen. Retrieved on startup from bridge, and potentially modified locally.
|
||||
QString goos_; ///< The cached version of the GOOS variable.
|
||||
QUrl logsPath_; ///< The logs path. Retrieved from bridge on startup.
|
||||
QUrl licensePath_; ///< The license path. Retrieved from bridge on startup.
|
||||
|
||||
friend class AppController;
|
||||
};
|
||||
|
||||
|
||||
#endif // BRIDGE_GUI_QML_BACKEND_H
|
||||
@ -1,70 +0,0 @@
|
||||
## Prerequisite
|
||||
|
||||
### Linux (debian and derivates)
|
||||
```` bash
|
||||
sudo apt install build-essential
|
||||
sudo apt install tar curl zip unzip
|
||||
sudo apt install linux-headers-$(uname -r)
|
||||
sudo apt install mesa-common-dev libglu1-mesa-dev
|
||||
````
|
||||
|
||||
### macOS & WIndows
|
||||
|
||||
Coming soon...
|
||||
|
||||
|
||||
### Define QT6DIR
|
||||
|
||||
``` bash
|
||||
export QT6DIR=/opt/Qt/6.3.1/gcc_64
|
||||
```
|
||||
|
||||
### install vcpkg and define VCPKG_ROOT
|
||||
|
||||
``` bash
|
||||
git clone https://github.com/Microsoft/vcpkg.git
|
||||
./vcpkg/bootstrap-vcpkg.sh
|
||||
export VCPKG_ROOT=$PWD/vcpkg
|
||||
```
|
||||
|
||||
## install grpc & protobuf
|
||||
|
||||
``` bash
|
||||
./vcpkg install grpc
|
||||
```
|
||||
|
||||
## Building
|
||||
|
||||
A simple script is provided that run the appropriate CMake command.
|
||||
|
||||
``` bash
|
||||
./build.sh
|
||||
```
|
||||
|
||||
## Running
|
||||
|
||||
Simply run from the cmake build folder (`cmake-build-debug` by default)
|
||||
``` bash
|
||||
./bridge-gui
|
||||
```
|
||||
|
||||
`bridge-gui` will launch the `bridge` executable that it will try to locate in
|
||||
|
||||
- The working directory.
|
||||
- The application directory.
|
||||
- `cmd/Desktop-Bridge/`, `../cmd/Desktop-Bridge/`, `../../cmd/Desktop-Bridge`
|
||||
(up to five parent folders above the current folder are inspected).
|
||||
|
||||
you can specify the location of the bridge executable using the `-b` or
|
||||
`--bridge-exe-path` command-line parameter:
|
||||
|
||||
``` bash
|
||||
./bridge-gui -b "~/bin/bridge"
|
||||
```
|
||||
|
||||
you can also ask bridge-gui to connect to an already running instance of `bridge`
|
||||
using the `-a` or `--attach` command line parameter.
|
||||
|
||||
``` bash
|
||||
./bridge-gui -a
|
||||
```
|
||||
@ -1,118 +0,0 @@
|
||||
<!-- GODT-1687 This file can probably be auto-generated-->
|
||||
<!DOCTYPE RCC><RCC version="1.0">
|
||||
<qresource>
|
||||
<file>qml/AccountDelegate.qml</file>
|
||||
<file>qml/AccountView.qml</file>
|
||||
<file>qml/Banner.qml</file>
|
||||
<file>qml/Bridge.qml</file>
|
||||
<file>qml/Bridge_test.qml</file>
|
||||
<file>qml/bridgeqml.qmlproject</file>
|
||||
<file>qml/BridgeTest/UserControl.qml</file>
|
||||
<file>qml/BridgeTest/UserList.qml</file>
|
||||
<file>qml/BridgeTest/UserModel.qml</file>
|
||||
<file>qml/BugReportView.qml</file>
|
||||
<file>qml/Configuration.qml</file>
|
||||
<file>qml/ConfigurationItem.qml</file>
|
||||
<file>qml/ContentWrapper.qml</file>
|
||||
<file>qml/DebugWrapper.qml</file>
|
||||
<file>qml/GeneralSettings.qml</file>
|
||||
<file>qml/HelpView.qml</file>
|
||||
<file>qml/icons/ic-alert.svg</file>
|
||||
<file>qml/icons/ic-apple-mail.svg</file>
|
||||
<file>qml/icons/ic-arrow-left.svg</file>
|
||||
<file>qml/icons/ic-card-identity.svg</file>
|
||||
<file>qml/icons/ic-check.svg</file>
|
||||
<file>qml/icons/ic-chevron-down.svg</file>
|
||||
<file>qml/icons/ic-chevron-up.svg</file>
|
||||
<file>qml/icons/ic-cog-wheel.svg</file>
|
||||
<file>qml/icons/ic-connected.svg</file>
|
||||
<file>qml/icons/ic-copy.svg</file>
|
||||
<file>qml/icons/ic-cross-close.svg</file>
|
||||
<file>qml/icons/ic-drive.svg</file>
|
||||
<file>qml/icons/ic-exclamation-circle-filled.svg</file>
|
||||
<file>qml/icons/ic-external-link.svg</file>
|
||||
<file>qml/icons/ic-eye-slash.svg</file>
|
||||
<file>qml/icons/ic-eye.svg</file>
|
||||
<file>qml/icons/ic-illustrative-view-html-code.svg</file>
|
||||
<file>qml/icons/ic-info-circle-filled.svg</file>
|
||||
<file>qml/icons/ic-info.svg</file>
|
||||
<file>qml/icons/ic-microsoft-outlook.svg</file>
|
||||
<file>qml/icons/ic-mozilla-thunderbird.svg</file>
|
||||
<file>qml/icons/ic-no-connection.svg</file>
|
||||
<file>qml/icons/ic-other-mail-clients.svg</file>
|
||||
<file>qml/icons/ic-plus.svg</file>
|
||||
<file>qml/icons/ic-question-circle.svg</file>
|
||||
<file>qml/icons/ic-success.svg</file>
|
||||
<file>qml/icons/ic-three-dots-vertical.svg</file>
|
||||
<file>qml/icons/ic-trash.svg</file>
|
||||
<file>qml/icons/img-proton-logos.png</file>
|
||||
<file>qml/icons/img-proton-logos.svg</file>
|
||||
<file>qml/icons/img-splash.png</file>
|
||||
<file>qml/icons/img-splash.svg</file>
|
||||
<file>qml/icons/img-welcome-dark.png</file>
|
||||
<file>qml/icons/img-welcome-dark.svg</file>
|
||||
<file>qml/icons/img-welcome.png</file>
|
||||
<file>qml/icons/img-welcome.svg</file>
|
||||
<file>qml/icons/Loader_16.svg</file>
|
||||
<file>qml/icons/Loader_48.svg</file>
|
||||
<file>qml/icons/product_logos.svg</file>
|
||||
<file>qml/icons/product_logos_dark.svg</file>
|
||||
<file>qml/icons/systray-color-error.png</file>
|
||||
<file>qml/icons/systray-color-norm.png</file>
|
||||
<file>qml/icons/systray-color-update.png</file>
|
||||
<file>qml/icons/systray-color-warn.png</file>
|
||||
<file>qml/icons/systray-mono-error.png</file>
|
||||
<file>qml/icons/systray-mono-norm.png</file>
|
||||
<file>qml/icons/systray-mono-update.png</file>
|
||||
<file>qml/icons/systray-mono-warn.png</file>
|
||||
<file>qml/icons/systray.svg</file>
|
||||
<file alias="bridge.svg">../../../../dist/bridge.svg</file>
|
||||
<file>qml/KeychainSettings.qml</file>
|
||||
<file>qml/LocalCacheSettings.qml</file>
|
||||
<file>qml/MainWindow.qml</file>
|
||||
<file>qml/NotificationDialog.qml</file>
|
||||
<file>qml/NotificationPopups.qml</file>
|
||||
<file>qml/Notifications/Notification.qml</file>
|
||||
<file>qml/Notifications/NotificationFilter.qml</file>
|
||||
<file>qml/Notifications/Notifications.qml</file>
|
||||
<file>qml/Notifications/qmldir</file>
|
||||
<file>qml/PortSettings.qml</file>
|
||||
<file>qml/Proton/Action.qml</file>
|
||||
<file>qml/Proton/ApplicationWindow.qml</file>
|
||||
<file>qml/Proton/Button.qml</file>
|
||||
<file>qml/Proton/CheckBox.qml</file>
|
||||
<file>qml/Proton/ColorScheme.qml</file>
|
||||
<file>qml/Proton/ComboBox.qml</file>
|
||||
<file>qml/Proton/Dialog.qml</file>
|
||||
<file>qml/Proton/Label.qml</file>
|
||||
<file>qml/Proton/Menu.qml</file>
|
||||
<file>qml/Proton/MenuItem.qml</file>
|
||||
<file>qml/Proton/Popup.qml</file>
|
||||
<file>qml/Proton/qmldir</file>
|
||||
<file>qml/Proton/RadioButton.qml</file>
|
||||
<file>qml/Proton/Style.qml</file>
|
||||
<file>qml/Proton/Switch.qml</file>
|
||||
<file>qml/Proton/TextArea.qml</file>
|
||||
<file>qml/Proton/TextField.qml</file>
|
||||
<file>qml/Proton/Toggle.qml</file>
|
||||
<file>qml/SettingsItem.qml</file>
|
||||
<file>qml/SettingsView.qml</file>
|
||||
<file>qml/SetupGuide.qml</file>
|
||||
<file>qml/SignIn.qml</file>
|
||||
<file>qml/SMTPSettings.qml</file>
|
||||
<file>qml/SplashScreen.qml</file>
|
||||
<file>qml/Status.qml</file>
|
||||
<file>qml/StatusWindow.qml</file>
|
||||
<file>qml/tests/Buttons.qml</file>
|
||||
<file>qml/tests/ButtonsColumn.qml</file>
|
||||
<file>qml/tests/CheckBoxes.qml</file>
|
||||
<file>qml/tests/ComboBoxes.qml</file>
|
||||
<file>qml/tests/RadioButtons.qml</file>
|
||||
<file>qml/tests/Switches.qml</file>
|
||||
<file>qml/tests/Test.qml</file>
|
||||
<file>qml/tests/TestComponents.qml</file>
|
||||
<file>qml/tests/TextAreas.qml</file>
|
||||
<file>qml/tests/TextFields.qml</file>
|
||||
<file>qml/WelcomeGuide.qml</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
@ -1,26 +0,0 @@
|
||||
IDI_ICON1 ICON DISCARDABLE "${BRIDGE_REPO_ROOT}/dist/bridge.ico"
|
||||
|
||||
1 VERSIONINFO
|
||||
FILEVERSION ${BRIDGE_APP_VERSION_COMMA}
|
||||
PRODUCTVERSION ${BRIDGE_APP_VERSION_COMMA}
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904b0"
|
||||
BEGIN
|
||||
VALUE "Comments", "The Bridge is an application that runs on your computer in the background and seamlessly encrypts and decrypts your mail as it enters and leaves your computer."
|
||||
VALUE "CompanyName", "${BRIDGE_VENDOR}"
|
||||
VALUE "FileDescription", "${BRIDGE_APP_FULL_NAME}"
|
||||
VALUE "FileVersion", "${BRIDGE_APP_VERSION_COMMA}"
|
||||
VALUE "InternalName", "${PROJECT_NAME}.exe"
|
||||
VALUE "LegalCopyright", "(C) ${BRIDGE_BUILD_YEAR} ${BRIDGE_VENDOR}"
|
||||
VALUE "OriginalFilename", "${PROJECT_NAME}.exe"
|
||||
VALUE "ProductName", "${BRIDGE_APP_FULL_NAME} for Windows"
|
||||
VALUE "ProductVersion", "${BRIDGE_APP_VERSION}"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x0409, 0x04B0
|
||||
END
|
||||
END
|
||||
@ -1,231 +0,0 @@
|
||||
// Copyright (c) 2022 Proton AG
|
||||
//
|
||||
// This file is part of Proton Mail Bridge.
|
||||
//
|
||||
// Proton Mail Bridge is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Proton Mail Bridge is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
#include "UserList.h"
|
||||
|
||||
|
||||
using namespace bridgepp;
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] parent The parent object of the user list.
|
||||
//****************************************************************************************************************************************************
|
||||
UserList::UserList(QObject *parent)
|
||||
: QAbstractListModel(parent)
|
||||
{
|
||||
/// \todo use mutex to prevent concurrent access
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
//
|
||||
//****************************************************************************************************************************************************
|
||||
void UserList::connectGRPCEvents() const
|
||||
{
|
||||
GRPCClient& client = app().grpc();
|
||||
connect(&client, &GRPCClient::userChanged, this, &UserList::onUserChanged);
|
||||
connect(&client, &GRPCClient::toggleSplitModeFinished, this, &UserList::onToggleSplitModeFinished);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
//
|
||||
//****************************************************************************************************************************************************
|
||||
int UserList::rowCount(QModelIndex const &) const
|
||||
{
|
||||
return users_.size();
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] index The index to retrieve data for.
|
||||
/// \param[in] role The role to retrieve data for.
|
||||
/// \return The data at the index for the given role.
|
||||
//****************************************************************************************************************************************************
|
||||
QVariant UserList::data(QModelIndex const &index, int role) const
|
||||
{
|
||||
/// This It does not seem to be used, but the method is required by the base class.
|
||||
/// From the original QtThe recipe QML backend User model, the User is always returned, regardless of the role.
|
||||
Q_UNUSED(role)
|
||||
int const row = index.row();
|
||||
if ((row < 0) || (row >= users_.size()))
|
||||
return QVariant();
|
||||
return QVariant::fromValue(users_[row].get());
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] userID The userID.
|
||||
/// \return the row of the user.
|
||||
/// \return -1 if the userID is not in the list
|
||||
//****************************************************************************************************************************************************
|
||||
int UserList::rowOfUserID(QString const &userID) const
|
||||
{
|
||||
for (qint32 row = 0; row < users_.count(); ++row)
|
||||
if (userID == users_[row]->property("id"))
|
||||
return row;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] users The new user list.
|
||||
//****************************************************************************************************************************************************
|
||||
void UserList::reset(QList<SPUser> const &users)
|
||||
{
|
||||
this->beginResetModel();
|
||||
users_ = users;
|
||||
this->endResetModel();
|
||||
emit countChanged(users_.size());
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] user The user.
|
||||
//****************************************************************************************************************************************************
|
||||
void UserList::appendUser(SPUser const &user)
|
||||
{
|
||||
user->setSetupGuideSeen(false);
|
||||
int const size = users_.size();
|
||||
this->beginInsertRows(QModelIndex(), size, size);
|
||||
users_.append(user);
|
||||
this->endInsertRows();
|
||||
emit countChanged(users_.size());
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] row The row.
|
||||
//****************************************************************************************************************************************************
|
||||
void UserList::removeUserAt(int row)
|
||||
{
|
||||
if ((row < 0) && (row >= users_.size()))
|
||||
return;
|
||||
this->beginRemoveRows(QModelIndex(), row, row);
|
||||
users_.removeAt(row);
|
||||
this->endRemoveRows();
|
||||
emit countChanged(users_.size());
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] row The row.
|
||||
/// \param[in] user The user.
|
||||
//****************************************************************************************************************************************************
|
||||
void UserList::updateUserAtRow(int row, User const &user)
|
||||
{
|
||||
if ((row < 0) || (row >= users_.count()))
|
||||
{
|
||||
app().log().error(QString("invalid user at row %2 (user userCount = %2)").arg(row).arg(users_.count()));
|
||||
return;
|
||||
}
|
||||
|
||||
users_[row]->update(user);
|
||||
|
||||
QModelIndex modelIndex = this->index(row);
|
||||
emit dataChanged(modelIndex, modelIndex);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] userID The userID.
|
||||
/// \return The user with the given ID.
|
||||
/// \return A null pointer if the user could not be found.
|
||||
//****************************************************************************************************************************************************
|
||||
bridgepp::SPUser UserList::getUserWithID(QString const &userID) const
|
||||
{
|
||||
QList<SPUser>::const_iterator it = std::find_if(users_.begin(), users_.end(), [userID](SPUser const & user) -> bool {
|
||||
return user && user->id() == userID; });
|
||||
return (it == users_.end()) ? nullptr : *it;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] row The row.
|
||||
//****************************************************************************************************************************************************
|
||||
User *UserList::get(int row) const
|
||||
{
|
||||
if ((row < 0) || (row >= users_.count()))
|
||||
{
|
||||
app().log().error(QString("Requesting invalid user at row %1 (user userCount = %2)").arg(row).arg(users_.count()));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
app().log().debug(QString("Retrieving user at row %1 (user userCount = %2)").arg(row).arg(users_.count()));
|
||||
return users_[row].get();
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] userID The userID.
|
||||
//****************************************************************************************************************************************************
|
||||
void UserList::onUserChanged(QString const &userID)
|
||||
{
|
||||
int const index = this->rowOfUserID(userID);
|
||||
SPUser user;
|
||||
grpc::Status status = app().grpc().getUser(userID, user);
|
||||
QQmlEngine::setObjectOwnership(user.get(), QQmlEngine::CppOwnership);
|
||||
|
||||
if ((!user) || (!status.ok()))
|
||||
{
|
||||
if (index >= 0) // user exists here but not in the go backend. we delete it.
|
||||
{
|
||||
app().log().debug(QString("Removing user from user list: %1").arg(userID));
|
||||
this->removeUserAt(index);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (index < 0)
|
||||
{
|
||||
app().log().debug(QString("Adding user in user list: %1").arg(userID));
|
||||
this->appendUser(user);
|
||||
return;
|
||||
}
|
||||
|
||||
app().log().debug(QString("Updating user in user list: %1").arg(userID));
|
||||
this->updateUserAtRow(index, *user);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// The only purpose of this function is to forward the toggleSplitModeFinished event received from gRPC to the
|
||||
/// appropriate user.
|
||||
///
|
||||
/// \param[in] userID the userID.
|
||||
//****************************************************************************************************************************************************
|
||||
void UserList::onToggleSplitModeFinished(QString const &userID)
|
||||
{
|
||||
int const index = this->rowOfUserID(userID);
|
||||
if (index < 0)
|
||||
{
|
||||
app().log().error(QString("Received toggleSplitModeFinished event for unknown userID %1").arg(userID));
|
||||
return;
|
||||
}
|
||||
|
||||
users_[index]->emitToggleSplitModeFinished();
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return THe number of items in the list.
|
||||
//****************************************************************************************************************************************************
|
||||
int UserList::count() const
|
||||
{
|
||||
return users_.size();
|
||||
}
|
||||
@ -1,68 +0,0 @@
|
||||
// Copyright (c) 2022 Proton AG
|
||||
//
|
||||
// This file is part of Proton Mail Bridge.
|
||||
//
|
||||
// Proton Mail Bridge is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Proton Mail Bridge is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
#ifndef BRIDGE_GUI_USER_LIST_H
|
||||
#define BRIDGE_GUI_USER_LIST_H
|
||||
|
||||
|
||||
#include <bridgepp/User/User.h>
|
||||
#include <bridgepp/Log/Log.h>
|
||||
#include <bridgepp/GRPC/GRPCClient.h>
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \brief User list class.
|
||||
//****************************************************************************************************************************************************
|
||||
class UserList : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public: // member functions.
|
||||
UserList(QObject *parent); ///< Default constructor.
|
||||
UserList(UserList const &other) = delete; ///< Disabled copy-constructor.
|
||||
UserList &operator=(UserList const &other) = delete; ///< Disabled assignment operator.
|
||||
~UserList() override = default; ///< Destructor
|
||||
void connectGRPCEvents() const; ///< Connects gRPC event to the model.
|
||||
int rowCount(QModelIndex const &parent) const override; ///< Return the number of row in the model
|
||||
QVariant data(QModelIndex const &index, int role) const override; ///< Retrieve model data.
|
||||
void reset(QList<bridgepp::SPUser> const &users); ///< Replace the user list.
|
||||
int rowOfUserID(QString const &userID) const;
|
||||
void removeUserAt(int row); ///< Remove the user at a given row
|
||||
void appendUser(bridgepp::SPUser const &user); ///< Add a new user.
|
||||
void updateUserAtRow(int row, bridgepp::User const &user); ///< Update the user at given row.
|
||||
bridgepp::SPUser getUserWithID(QString const& userID) const; ///< Retrieve the user with the given ID.
|
||||
|
||||
// the userCount property.
|
||||
Q_PROPERTY(int count READ count NOTIFY countChanged)
|
||||
int count() const; ///< The userCount property getter.
|
||||
|
||||
signals:
|
||||
void countChanged(int count); ///< Signal for the userCount property.
|
||||
|
||||
public:
|
||||
Q_INVOKABLE bridgepp::User *get(int row) const;
|
||||
|
||||
public slots: ///< handler for signals coming from the gRPC service
|
||||
void onUserChanged(QString const &userID);
|
||||
void onToggleSplitModeFinished(QString const &userID);
|
||||
|
||||
private: // data members
|
||||
QList<bridgepp::SPUser> users_; ///< The user list.
|
||||
};
|
||||
|
||||
|
||||
#endif // BRIDGE_GUI_USER_LIST_H
|
||||
@ -1,28 +0,0 @@
|
||||
// Copyright (c) 2022 Proton AG
|
||||
//
|
||||
// This file is part of Proton Mail Bridge.
|
||||
//
|
||||
// Proton Mail Bridge is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Proton Mail Bridge is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
#ifndef BRIDGE_GUI_VERSION_H
|
||||
#define BRIDGE_GUI_VERSION_H
|
||||
|
||||
#define PROJECT_FULL_NAME "@BRIDGE_APP_FULL_NAME@"
|
||||
#define PROJECT_VENDOR "@BRIDGE_VENDOR@"
|
||||
#define PROJECT_VER "@BRIDGE_APP_VERSION@"
|
||||
#define PROJECT_REVISION "@BRIDGE_REVISION@"
|
||||
#define PROJECT_BUILD_TIME "@BRIDGE_BUILD_TIME@"
|
||||
|
||||
#endif // BRIDGE_GUI_VERSION_H
|
||||
@ -1,101 +0,0 @@
|
||||
# Copyright (c) 2022 Proton AG
|
||||
#
|
||||
# This file is part of Proton Mail Bridge.
|
||||
#
|
||||
# Proton Mail Bridge is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Proton Mail Bridge is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#!/bin/bash
|
||||
|
||||
$scriptpath = $MyInvocation.MyCommand.Path
|
||||
$scriptDir = Split-Path $scriptpath
|
||||
$bridgeRepoRootDir = Join-Path $scriptDir "../../../.." -Resolve
|
||||
Write-host "Bridge-gui directory is $scriptDir"
|
||||
Write-host "Bridge repos root dir $bridgeRepoRootDir"
|
||||
Push-Location $scriptDir
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
$cmakeExe=$(Get-Command cmake).source
|
||||
if ($null -eq $cmakeExe)
|
||||
{
|
||||
$cmakeExe = "C:\Program Files\Microsoft Visual Studio\2022\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin\cmake.exe" # Hardcoded for now.
|
||||
}
|
||||
Write-host "CMake found here : $cmakeExe"
|
||||
$cmake_version = . $cmakeExe --version
|
||||
Write-host "CMake version : $cmake_version"
|
||||
|
||||
$bridgeVersion = ($env:BRIDGE_APP_VERSION)
|
||||
if ($null -eq $bridgeVersion)
|
||||
{
|
||||
$bridgeVersion = . (Join-Path $bridgeRepoRootDir "utils/bridge_app_version.ps1")
|
||||
}
|
||||
|
||||
$bridgeFullName = ($env:BRIDGE_APP_FULL_NAME)
|
||||
if ($null -eq $bridgeFullName)
|
||||
{
|
||||
$bridgeFullName = "Proton Mail Bridge"
|
||||
}
|
||||
|
||||
$bridgeVendor = ($env:BRIDGE_VENDOR)
|
||||
if ($null -eq $bridgeVendor)
|
||||
{
|
||||
$bridgeVendor = "Proton AG"
|
||||
}
|
||||
|
||||
$buildConfig = ($env:BRIDGE_GUI_BUILD_CONFIG)
|
||||
if ($null -eq $buildConfig)
|
||||
{
|
||||
$buildConfig = "Debug"
|
||||
}
|
||||
|
||||
$buildDir=(Join-Path $scriptDir "cmake-build-$buildConfig".ToLower())
|
||||
$vcpkgRoot = (Join-Path $bridgeRepoRootDir "extern/vcpkg" -Resolve)
|
||||
$vcpkgExe = (Join-Path $vcpkgRoot "vcpkg.exe")
|
||||
$vcpkgBootstrap = (Join-Path $vcpkgRoot "bootstrap-vcpkg.bat")
|
||||
|
||||
function check_exit() {
|
||||
if ($? -ne $True)
|
||||
{
|
||||
Write-Host "Process failed: $args[0] : $?"
|
||||
Remove-Item "$buildDir" -Recurse -ErrorAction Ignore
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
|
||||
Write-host "Running build for version $bridgeVersion - $buildConfig in $buildDir"
|
||||
|
||||
git submodule update --init --recursive $vcpkgRoot
|
||||
. $vcpkgBootstrap -disableMetrics
|
||||
. $vcpkgExe install grpc:x64-windows --clean-after-build
|
||||
. $vcpkgExe upgrade --no-dry-run
|
||||
. $cmakeExe -G "Visual Studio 17 2022" -DCMAKE_BUILD_TYPE="$buildConfig" `
|
||||
-DBRIDGE_APP_FULL_NAME="$bridgeFullName" `
|
||||
-DBRIDGE_VENDOR="$bridgeVendor" `
|
||||
-DBRIDGE_APP_VERSION="$bridgeVersion" `
|
||||
-S . -B $buildDir
|
||||
|
||||
check_exit "CMake failed"
|
||||
. $cmakeExe --build $buildDir --config "$buildConfig"
|
||||
check_exit "Build failed"
|
||||
|
||||
if ($($args.count) -gt 0 )
|
||||
{
|
||||
if ($args[0] = "install")
|
||||
{
|
||||
. $cmakeExe --install $buildDir
|
||||
check_exit "Install failed"
|
||||
}
|
||||
}
|
||||
|
||||
Pop-Location
|
||||
@ -1,104 +0,0 @@
|
||||
#!/bin/bash
|
||||
# Copyright (c) 2022 Proton AG
|
||||
#
|
||||
# This file is part of Proton Mail Bridge.
|
||||
#
|
||||
# Proton Mail Bridge is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Proton Mail Bridge is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
if [[ "$OSTYPE" == "msys" ]] || [[ "$OSTYPE" == "win32" ]] ; then
|
||||
Powershell.exe -File build.ps1 "$@"
|
||||
exit $?
|
||||
fi
|
||||
|
||||
set -x
|
||||
|
||||
realpath() {
|
||||
START_DIR=$PWD
|
||||
BASENAME="$(basename "$1")"
|
||||
cd "$(dirname "$1")" || exit
|
||||
LNK="$(readlink "$BASENAME")"
|
||||
while [ "$LNK" ]; do
|
||||
BASENAME="$(basename "$LNK")"
|
||||
cd "$(dirname "$LNK")" || exit
|
||||
LNK="$(readlink "$BASENAME")"
|
||||
done
|
||||
REALPATH="$PWD/$BASENAME"
|
||||
cd "$START_DIR" || exit
|
||||
echo "$REALPATH"
|
||||
}
|
||||
|
||||
check_exit() {
|
||||
# shellcheck disable=SC2181
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Process failed: $1"
|
||||
rm -r "$BUILD_DIR"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
BRIDGE_REPO_ROOT=$(realpath "../../../..")
|
||||
BRIDGE_INSTALL_PATH=${BRIDGE_INSTALL_PATH:-deploy}
|
||||
BRIDGE_APP_VERSION=${BRIDGE_APP_VERSION:-$("${BRIDGE_REPO_ROOT}/utils/bridge_app_version.sh")}
|
||||
BRIDGE_APP_FULL_NAME=${BRIDGE_APP_FULL_NAME:-"Proton Mail Bridge"}
|
||||
BRIDGE_VENDOR=${BRIDGE_VENDOR:-"Proton AG"}
|
||||
BUILD_CONFIG=${BRIDGE_GUI_BUILD_CONFIG:-Debug}
|
||||
BUILD_DIR=$(echo "./cmake-build-${BUILD_CONFIG}" | tr '[:upper:]' '[:lower:]')
|
||||
VCPKG_ROOT="${BRIDGE_REPO_ROOT}/extern/vcpkg"
|
||||
|
||||
git submodule update --init --recursive ${VCPKG_ROOT}
|
||||
check_exit "Failed to initialize vcpkg as a submodule."
|
||||
|
||||
echo submodule udpated
|
||||
|
||||
VCPKG_EXE="${VCPKG_ROOT}/vcpkg"
|
||||
VCPKG_BOOTSTRAP="${VCPKG_ROOT}/bootstrap-vcpkg.sh"
|
||||
|
||||
|
||||
${VCPKG_BOOTSTRAP} -disableMetrics
|
||||
check_exit "Failed to bootstrap vcpkg."
|
||||
|
||||
if [[ "$OSTYPE" == "darwin"* ]]; then
|
||||
if [[ "$(uname -m)" == "arm64" ]]; then
|
||||
${VCPKG_EXE} install grpc:arm64-osx --clean-after-build
|
||||
check_exit "Failed installing gRPC for macOS / Apple Silicon"
|
||||
fi
|
||||
${VCPKG_EXE} install grpc:x64-osx --clean-after-build
|
||||
check_exit "Failed installing gRPC for macOS / Intel x64"
|
||||
elif [[ "$OSTYPE" == "linux"* ]]; then
|
||||
${VCPKG_EXE} install grpc:x64-linux --clean-after-build
|
||||
check_exit "Failed installing gRPC for Linux / Intel x64"
|
||||
else
|
||||
echo "For Windows, use the build.ps1 Powershell script."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
${VCPKG_EXE} upgrade --no-dry-run
|
||||
|
||||
cmake \
|
||||
-DCMAKE_BUILD_TYPE="${BUILD_CONFIG}" \
|
||||
-DBRIDGE_APP_FULL_NAME="${BRIDGE_APP_FULL_NAME}" \
|
||||
-DBRIDGE_VENDOR="${BRIDGE_VENDOR}" \
|
||||
-DBRIDGE_APP_VERSION="${BRIDGE_APP_VERSION}" \
|
||||
-G Ninja \
|
||||
-S . \
|
||||
-B "${BUILD_DIR}"
|
||||
check_exit "CMake failed"
|
||||
|
||||
cmake --build "${BUILD_DIR}"
|
||||
check_exit "build failed"
|
||||
|
||||
if [ "$1" == "install" ]; then
|
||||
cmake --install "${BUILD_DIR}"
|
||||
check_exit "install failed"
|
||||
fi
|
||||
@ -1,373 +0,0 @@
|
||||
// Copyright (c) 2022 Proton AG
|
||||
//
|
||||
// This file is part of Proton Mail Bridge.
|
||||
//
|
||||
// Proton Mail Bridge is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Proton Mail Bridge is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
#include "QMLBackend.h"
|
||||
#include "Version.h"
|
||||
#include <bridgepp/Log/Log.h>
|
||||
#include <bridgepp/BridgeUtils.h>
|
||||
#include <bridgepp/Exception/Exception.h>
|
||||
#include <bridgepp/ProcessMonitor.h>
|
||||
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QNetworkRequest>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
|
||||
using namespace bridgepp;
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
/// \brief The file extension for the bridge executable file.
|
||||
#ifdef Q_OS_WIN32
|
||||
QString const exeSuffix = ".exe";
|
||||
#else
|
||||
QString const exeSuffix;
|
||||
#endif
|
||||
|
||||
QString const launcherFlag = "--launcher"; ///< launcher flag parameter used for bridge.
|
||||
QString const bridgeLock = "bridge-gui.lock"; ///< file name used for the lock file.
|
||||
QString const exeName = "bridge" + exeSuffix; ///< The bridge executable file name.*
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return The path of the bridge executable.
|
||||
/// \return A null string if the executable could not be located.
|
||||
//****************************************************************************************************************************************************
|
||||
QString locateBridgeExe()
|
||||
{
|
||||
QFileInfo const fileInfo(QDir(QCoreApplication::applicationDirPath()).absoluteFilePath(exeName));
|
||||
return (fileInfo.exists() && fileInfo.isFile() && fileInfo.isExecutable()) ? fileInfo.absoluteFilePath() : QString();
|
||||
}
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// // initialize the Qt application.
|
||||
//****************************************************************************************************************************************************
|
||||
void initQtApplication()
|
||||
{
|
||||
QString const qsgInfo = QProcessEnvironment::systemEnvironment().value("QSG_INFO");
|
||||
if ((!qsgInfo.isEmpty()) && (qsgInfo != "0"))
|
||||
QLoggingCategory::setFilterRules("qt.scenegraph.general=true");
|
||||
|
||||
QGuiApplication::setApplicationName(PROJECT_FULL_NAME);
|
||||
QGuiApplication::setApplicationVersion(PROJECT_VER);
|
||||
QGuiApplication::setOrganizationName(PROJECT_VENDOR);
|
||||
QGuiApplication::setOrganizationDomain("proton.ch");
|
||||
QGuiApplication::setQuitOnLastWindowClosed(false);
|
||||
QGuiApplication::setWindowIcon(QIcon(":bridge.svg"));
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return A reference to the log.
|
||||
//****************************************************************************************************************************************************
|
||||
Log &initLog()
|
||||
{
|
||||
Log &log = app().log();
|
||||
log.setEchoInConsole(true);
|
||||
log.setLevel(Log::Level::Debug);
|
||||
log.registerAsQtMessageHandler();
|
||||
return log;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] engine The QML component.
|
||||
//****************************************************************************************************************************************************
|
||||
QQmlComponent *createRootQmlComponent(QQmlApplicationEngine &engine)
|
||||
{
|
||||
QString const qrcQmlDir = "qrc:/qml";
|
||||
|
||||
qmlRegisterSingletonInstance("Proton", 1, 0, "Backend", &app().backend());
|
||||
qmlRegisterType<UserList>("Proton", 1, 0, "UserList");
|
||||
qmlRegisterType<bridgepp::User>("Proton", 1, 0, "User");
|
||||
|
||||
auto rootComponent = new QQmlComponent(&engine, &engine);
|
||||
|
||||
engine.addImportPath(qrcQmlDir);
|
||||
engine.addPluginPath(qrcQmlDir);
|
||||
QQuickStyle::setStyle("Proton");
|
||||
|
||||
rootComponent->loadUrl(QUrl(qrcQmlDir + "/Bridge.qml"));
|
||||
if (rootComponent->status() != QQmlComponent::Status::Ready)
|
||||
{
|
||||
app().log().error(rootComponent->errorString());
|
||||
throw Exception("Could not load QML component");
|
||||
}
|
||||
return rootComponent;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] lock The lock file to be checked.
|
||||
/// \return True if the lock can be taken, false otherwise.
|
||||
//****************************************************************************************************************************************************
|
||||
bool checkSingleInstance(QLockFile &lock)
|
||||
{
|
||||
lock.setStaleLockTime(0);
|
||||
if (!lock.tryLock())
|
||||
{
|
||||
qint64 pid;
|
||||
QString hostname, appName, details;
|
||||
if (lock.getLockInfo(&pid, &hostname, &appName))
|
||||
details = QString("(PID : %1 - Host : %2 - App : %3)").arg(pid).arg(hostname, appName);
|
||||
|
||||
app().log().error(QString("Instance already exists %1 %2").arg(lock.fileName(), details));
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
app().log().info(QString("lock file created %1").arg(lock.fileName()));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return QUrl to reqch the bridge API.
|
||||
//****************************************************************************************************************************************************
|
||||
QUrl getApiUrl()
|
||||
{
|
||||
QUrl url;
|
||||
// use default url.
|
||||
url.setScheme("http");
|
||||
url.setHost("127.0.0.1");
|
||||
url.setPort(1042);
|
||||
|
||||
// override with what can be found in the prefs.json file.
|
||||
QFile prefFile(QString("%1/%2").arg(bridgepp::userConfigDir(), "prefs.json"));
|
||||
if (prefFile.exists())
|
||||
{
|
||||
prefFile.open(QIODevice::ReadOnly|QIODevice::Text);
|
||||
QByteArray data = prefFile.readAll();
|
||||
prefFile.close();
|
||||
QJsonDocument doc = QJsonDocument::fromJson(data);
|
||||
if (!doc.isNull()) {
|
||||
QString userPortApi = "user_port_api";
|
||||
QJsonObject obj = doc.object();
|
||||
if (!obj.isEmpty() && obj.contains(userPortApi))
|
||||
url.setPort(doc.object()[userPortApi].toString().toInt());
|
||||
}
|
||||
}
|
||||
return url;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \brief Use api to bring focus on existing bridge instance.
|
||||
//****************************************************************************************************************************************************
|
||||
void focusOtherInstance()
|
||||
{
|
||||
QNetworkAccessManager *manager;
|
||||
QNetworkRequest request;
|
||||
manager = new QNetworkAccessManager();
|
||||
QUrl url = getApiUrl();
|
||||
url.setPath("/focus");
|
||||
request.setUrl(url);
|
||||
QNetworkReply* rep = manager->get(request);
|
||||
|
||||
QEventLoop loop;
|
||||
QObject::connect(rep, &QNetworkReply::finished, &loop, &QEventLoop::quit);
|
||||
loop.exec();
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param [in] argc number of arguments passed to the application.
|
||||
/// \param [in] argv list of arguments passed to the application.
|
||||
/// \param [out] args list of arguments passed to the application as a QStringList.
|
||||
/// \param [out] launcher launcher used in argument, forced to self application if not specify.
|
||||
/// \param[out] outAttach The value for the 'attach' command-line parameter.
|
||||
//****************************************************************************************************************************************************
|
||||
void parseArguments(int argc, char *argv[], QStringList& args, QString& launcher, bool &outAttach) {
|
||||
bool flagFound = false;
|
||||
launcher = QString::fromLocal8Bit(argv[0]);
|
||||
// for unknown reasons, on Windows QCoreApplication::arguments() frequently returns an empty list, which is incorrect, so we rebuild the argument
|
||||
// list from the original argc and argv values.
|
||||
for (int i = 1; i < argc; i++) {
|
||||
QString const &arg = QString::fromLocal8Bit(argv[i]);
|
||||
// we can't use QCommandLineParser here since it will fail on unknown options.
|
||||
// Arguments may contain some bridge flags.
|
||||
if (arg == launcherFlag)
|
||||
{
|
||||
args.append(arg);
|
||||
launcher = QString::fromLocal8Bit(argv[++i]);
|
||||
args.append(launcher);
|
||||
flagFound = true;
|
||||
}
|
||||
#ifdef QT_DEBUG
|
||||
else if (arg == "--attach" || arg == "-a")
|
||||
{
|
||||
// we don't keep the attach mode within the args since we don't need it for Bridge.
|
||||
outAttach = true;
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
args.append(arg);
|
||||
}
|
||||
}
|
||||
if (!flagFound)
|
||||
{
|
||||
// add bridge-gui as launcher
|
||||
args.append(launcherFlag);
|
||||
args.append(launcher);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param [in] args list of arguments to pass to bridge.
|
||||
//****************************************************************************************************************************************************
|
||||
void launchBridge(QStringList const &args)
|
||||
{
|
||||
UPOverseer& overseer = app().bridgeOverseer();
|
||||
overseer.reset();
|
||||
|
||||
const QString bridgeExePath = locateBridgeExe();
|
||||
|
||||
if (bridgeExePath.isEmpty())
|
||||
throw Exception("Could not locate the bridge executable path");
|
||||
else
|
||||
app().log().debug(QString("Bridge executable path: %1").arg(QDir::toNativeSeparators(bridgeExePath)));
|
||||
|
||||
overseer = std::make_unique<Overseer>(new ProcessMonitor(bridgeExePath, args, nullptr), nullptr);
|
||||
overseer->startWorker(true);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
//
|
||||
//****************************************************************************************************************************************************
|
||||
void closeBridgeApp()
|
||||
{
|
||||
app().grpc().quit(); // this will cause the grpc service and the bridge app to close.
|
||||
|
||||
UPOverseer& overseer = app().bridgeOverseer();
|
||||
if (!overseer) // The app was run in 'attach' mode and attached to an existing instance of Bridge. We're not monitoring it.
|
||||
return;
|
||||
|
||||
while (!overseer->isFinished())
|
||||
{
|
||||
QThread::msleep(20);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] argc The number of command-line arguments.
|
||||
/// \param[in] argv The list of command-line arguments.
|
||||
/// \return The exit code for the application.
|
||||
//****************************************************************************************************************************************************
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
// The application instance is needed to display system message boxes. As we may have to do it in the exception handler,
|
||||
// application instance is create outside the try/catch clause.
|
||||
if (QSysInfo::productType() != "windows")
|
||||
QCoreApplication::setAttribute(Qt::AA_UseSoftwareOpenGL);
|
||||
QApplication guiApp(argc, argv);
|
||||
|
||||
try
|
||||
{
|
||||
initQtApplication();
|
||||
|
||||
Log &log = initLog();
|
||||
|
||||
QLockFile lock(bridgepp::userCacheDir() + "/" + bridgeLock);
|
||||
if (!checkSingleInstance(lock))
|
||||
{
|
||||
focusOtherInstance();
|
||||
return EXIT_FAILURE;
|
||||
|
||||
}
|
||||
QStringList args;
|
||||
QString launcher;
|
||||
bool attach = false;
|
||||
parseArguments(argc, argv, args, launcher, attach);
|
||||
|
||||
if (!attach)
|
||||
launchBridge(args);
|
||||
|
||||
app().backend().init();
|
||||
|
||||
QQmlApplicationEngine engine;
|
||||
std::unique_ptr<QQmlComponent> rootComponent(createRootQmlComponent(engine));
|
||||
std::unique_ptr<QObject>rootObject(rootComponent->create(engine.rootContext()));
|
||||
if (!rootObject)
|
||||
throw Exception("Could not create root object.");
|
||||
|
||||
ProcessMonitor *bridgeMonitor = app().bridgeMonitor();
|
||||
bool bridgeExited = false;
|
||||
bool startError = false;
|
||||
QMetaObject::Connection connection;
|
||||
if (bridgeMonitor)
|
||||
{
|
||||
const ProcessMonitor::MonitorStatus& status = bridgeMonitor->getStatus();
|
||||
if (!status.running && !attach)
|
||||
{
|
||||
// ProcessMonitor already stopped meaning we are attached to an orphan Bridge.
|
||||
// Restart the full process to be sure there is no more bridge orphans
|
||||
app().log().error("Found orphan bridge, need to restart.");
|
||||
app().backend().forceLauncher(launcher);
|
||||
app().backend().restart();
|
||||
bridgeExited = true;
|
||||
startError = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
app().log().debug(QString("Monitoring Bridge PID : %1").arg(status.pid));
|
||||
|
||||
connection = QObject::connect(bridgeMonitor, &ProcessMonitor::processExited, [&](int returnCode) {
|
||||
bridgeExited = true;// clazy:exclude=lambda-in-connect
|
||||
qGuiApp->exit(returnCode);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
int result = 0;
|
||||
if (!startError)
|
||||
{
|
||||
// we succeed to run the bridge so we can be set as mainExecutable.
|
||||
app().grpc().setMainExecutable(QString::fromLocal8Bit(argv[0]));
|
||||
result = QGuiApplication::exec();
|
||||
}
|
||||
|
||||
QObject::disconnect(connection);
|
||||
app().grpc().stopEventStreamReader();
|
||||
if (!app().backend().waitForEventStreamReaderToFinish(5000))
|
||||
log.warn("Event stream reader took too long to finish.");
|
||||
|
||||
// We manually delete the QML components to avoid warnings error due to order of deletion of C++ / JS objects and singletons.
|
||||
rootObject.reset();
|
||||
rootComponent.reset();
|
||||
|
||||
if (!bridgeExited)
|
||||
closeBridgeApp();
|
||||
// release the lock file
|
||||
lock.unlock();
|
||||
return result;
|
||||
}
|
||||
catch (Exception const &e)
|
||||
{
|
||||
QMessageBox::critical(nullptr, "Error", e.qwhat());
|
||||
QTextStream(stderr) << e.qwhat() << "\n";
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
@ -1,126 +0,0 @@
|
||||
# Copyright (c) 2022 Proton AG
|
||||
#
|
||||
# This file is part of Proton Mail Bridge.
|
||||
#
|
||||
# Proton Mail Bridge is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Proton Mail Bridge is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
cmake_minimum_required(VERSION 3.22)
|
||||
|
||||
set(BRIDGE_REPO_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/../../../..")
|
||||
include(../BridgeSetup.cmake)
|
||||
|
||||
|
||||
#****************************************************************************************************************************************************
|
||||
# Base project setup
|
||||
#****************************************************************************************************************************************************
|
||||
project(bridgepp LANGUAGES CXX)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
if (NOT DEFINED BRIDGE_APP_VERSION)
|
||||
message(FATAL_ERROR "BRIDGE_APP_VERSION is not defined.")
|
||||
else()
|
||||
message(STATUS "Bridge version is ${BRIDGE_APP_VERSION}")
|
||||
endif()
|
||||
|
||||
|
||||
#****************************************************************************************************************************************************
|
||||
# Qt
|
||||
#****************************************************************************************************************************************************
|
||||
if (NOT DEFINED ENV{QT6DIR})
|
||||
message(FATAL_ERROR "QT6DIR needs to be defined and point to the root of your Qt 6 folder (e.g. /Users/MyName/Qt/6.3.1/clang_64).")
|
||||
endif ()
|
||||
set(CMAKE_PREFIX_PATH $ENV{QT6DIR} ${CMAKE_PREFIX_PATH})
|
||||
find_package(Qt6 COMPONENTS Core REQUIRED)
|
||||
qt_standard_project_setup()
|
||||
|
||||
|
||||
#****************************************************************************************************************************************************
|
||||
# gRPC / Protobuf
|
||||
#****************************************************************************************************************************************************
|
||||
find_package(Protobuf CONFIG REQUIRED)
|
||||
message(STATUS "Using protobuf ${Protobuf_VERSION}")
|
||||
|
||||
find_package(gRPC CONFIG REQUIRED)
|
||||
message(STATUS "Using gRPC ${gRPC_VERSION}")
|
||||
|
||||
find_program(PROTOC_EXE protoc REQUIRED)
|
||||
message(STATUS "protoc found ${PROTOC_EXE}")
|
||||
|
||||
message(STATUS "grpc_cpp_plugin ${grpc_cpp_plugin}")
|
||||
|
||||
find_program(GRPC_CPP_PLUGIN grpc_cpp_plugin)
|
||||
if (NOT GRPC_CPP_PLUGIN)
|
||||
message(FATAL_ERROR "grpc_cpp_plugin exe could not be found. Please add it to your path. it should be located in \${VCPKG_ROOT}/installed/arm64-osx/tools/grpc")
|
||||
else ()
|
||||
message(STATUS "grpc_cpp_plugin found at ${GRPC_CPP_PLUGIN}")
|
||||
endif ()
|
||||
|
||||
set(PROTO_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../grpc")
|
||||
set(PROTO_FILE "${PROTO_DIR}/bridge.proto")
|
||||
set(GRPC_OUT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/bridgepp/GRPC")
|
||||
set(PROTO_CPP_FILE "${GRPC_OUT_DIR}/bridge.pb.cc")
|
||||
set(PROTO_H_FILE "${GRPC_OUT_DIR}/bridge.pb.h")
|
||||
set(GRPC_CPP_FILE "${GRPC_OUT_DIR}/bridge.grpc.pb.cc")
|
||||
set(GRPC_H_FILE "${GRPC_OUT_DIR}/bridge.grpc.pb.h")
|
||||
|
||||
|
||||
#*****************************************************************************************************************************************************
|
||||
# Source files and output
|
||||
#*****************************************************************************************************************************************************
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT
|
||||
${PROTO_CPP_FILE}
|
||||
${PROTO_H_FILE}
|
||||
${GRPC_CPP_FILE}
|
||||
${GRPC_H_FILE}
|
||||
COMMAND
|
||||
${PROTOC_EXE}
|
||||
ARGS
|
||||
--proto_path=${PROTO_DIR}
|
||||
--plugin=protoc-gen-grpc="${GRPC_CPP_PLUGIN}"
|
||||
--cpp_out=${GRPC_OUT_DIR}
|
||||
--grpc_out=${GRPC_OUT_DIR}
|
||||
${PROTO_FILE}
|
||||
DEPENDS
|
||||
${PROTO_FILE}
|
||||
COMMENT "Generating gPRC/Protobuf C++ code"
|
||||
)
|
||||
|
||||
|
||||
add_library(bridgepp
|
||||
bridgepp/BridgeUtils.cpp bridgepp/BridgeUtils.h
|
||||
bridgepp/Exception/Exception.h bridgepp/Exception/Exception.cpp
|
||||
bridgepp/GRPC/GRPCClient.cpp bridgepp/GRPC/GRPCClient.h
|
||||
bridgepp/GRPC/EventFactory.cpp bridgepp/GRPC/EventFactory.h
|
||||
bridgepp/GRPC/GRPCUtils.cpp bridgepp/GRPC/GRPCUtils.h
|
||||
${PROTO_CPP_FILE} ${PROTO_H_FILE} ${GRPC_CPP_FILE} ${GRPC_H_FILE}
|
||||
bridgepp/Log/Log.h bridgepp/Log/Log.cpp
|
||||
bridgepp/ProcessMonitor.cpp bridgepp/ProcessMonitor.h
|
||||
bridgepp/User/User.cpp bridgepp/User/User.h
|
||||
bridgepp/Worker/Worker.h bridgepp/Worker/Overseer.h bridgepp/Worker/Overseer.cpp
|
||||
)
|
||||
|
||||
target_include_directories(bridgepp PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
target_link_libraries(bridgepp
|
||||
Qt6::Core
|
||||
protobuf::libprotobuf
|
||||
gRPC::grpc++
|
||||
)
|
||||
|
||||
target_precompile_headers(bridgepp PRIVATE Pch.h)
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,201 +0,0 @@
|
||||
// Copyright (c) 2022 Proton AG
|
||||
//
|
||||
// This file is part of Proton Mail Bridge.
|
||||
//
|
||||
// Proton Mail Bridge is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Proton Mail Bridge is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
#include "BridgeUtils.h"
|
||||
#include "Exception/Exception.h"
|
||||
#include <random>
|
||||
|
||||
|
||||
namespace bridgepp
|
||||
{
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
|
||||
QString const configFolder = "protonmail/bridge";
|
||||
QMutex rngMutex; ///< the mutex to use when accessing the rng.
|
||||
|
||||
QStringList const firstNames {
|
||||
"James", "John", "Robert", "Michael", "William", "David", "Richard", "Charles", "Joseph", "Thomas", "Christopher", "Daniel", "Paul", "Mark",
|
||||
"Donald", "George", "Kenneth", "Steven", "Edward", "Brian", "Ronald", "Anthony", "Kevin", "Jason", "Matthew", "Gary", "Timothy", "Jose", "Larry",
|
||||
"Jeffrey", "Frank", "Scott", "Eric", "Stephen", "Andrew", "Raymond", "Jack", "Gregory", "Joshua", "Jerry", "Dennis", "Walter", "Patrick", "Peter",
|
||||
"Harold", "Douglas", "Henry", "Carl", "Arthur", "Ryan", "Mary", "Patricia", "Barbara", "Linda", "Elizabeth", "Maria", "Jennifer", "Susan",
|
||||
"Margaret", "Dorothy", "Lisa", "Nancy", "Karen", "Betty", "Helen", "Sandra", "Donna", "Ruth", "Sharon", "Michelle", "Laura", "Sarah", "Kimberly",
|
||||
"Deborah", "Jessica", "Shirley", "Cynthia", "Angela", "Emily", "Brenda", "Amy", "Anna", "Rebecca", "Virginia", "Kathleen", "Pamela", "Martha",
|
||||
"Debra", "Amanda", "Stephanie", "Caroline", "Christine", "Marie", "Janet", "Catherine", "Frances", "Ann", "Joyce", "Diane", "Alice",
|
||||
}; ///< List of common US first names. (source: census.gov)
|
||||
|
||||
|
||||
QStringList const lastNames {
|
||||
"Smith", "Johnson", "Williams", "Brown", "Jones", "Garcia", "Miller", "Davis", "Rodriguez", "Martinez", "Hernandez", "Lopez", "Gonzalez",
|
||||
"Wilson", "Anderson", "Thomas", "Taylor", "Moore", "Jackson", "Martin", "Lee", "Perez", "Thompson", "White", "Harris", "Sanchez", "Clark",
|
||||
"Ramirez", "Lewis", "Robinson", "Walker", "Young", "Allen", "King", "Wright", "Scott", "Torres", "Nguyen", "Hill", "Flores", "Green", "Adams",
|
||||
"Nelson", "Baker", "Hall", "Rivera", "Campbell", "Mitchell", "Carter", "Roberts", "Gomez", "Phillips", "Evans", "Turner", "Diaz", "Parker",
|
||||
"Cruz", "Edwards", "Collins", "Reyes", "Stewart", "Morris", "Morales", "Murphy", "Cook", "Rogers", "Gutierrez", "Ortiz", "Morgan", "Cooper",
|
||||
"Peterson", "Bailey", "Reed", "Kelly", "Howard", "Ramos", "Kim", "Cox", "Ward", "Richardson", "Watson", "Brooks", "Chavez", "Wood", "James",
|
||||
"Bennett", "Gray", "Mendoza", "Ruiz", "Hughes", "Price", "Alvarez", "Castillo", "Sanders", "Patel", "Myers", "Long", "Ross", "Foster", "Jimenez"
|
||||
}; ///< List of common US last names (source: census.gov)
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \brief Return the 64 bit Mersenne twister random number generator.
|
||||
//****************************************************************************************************************************************************
|
||||
std::mt19937_64& rng()
|
||||
{
|
||||
// Do not use for crypto. std::random_device is not good enough.
|
||||
static std::mt19937_64 generator = std::mt19937_64(std::random_device()());
|
||||
return generator;
|
||||
}
|
||||
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return user configuration directory used by bridge (based on Golang OS/File's UserConfigDir).
|
||||
//****************************************************************************************************************************************************
|
||||
QString userConfigDir()
|
||||
{
|
||||
QString dir;
|
||||
#ifdef Q_OS_WIN
|
||||
dir = qgetenv ("AppData");
|
||||
if (dir.isEmpty())
|
||||
throw Exception("%AppData% is not defined.");
|
||||
#elif defined(Q_OS_IOS) || defined(Q_OS_DARWIN)
|
||||
dir = qgetenv ("HOME");
|
||||
if (dir.isEmpty())
|
||||
throw Exception("$HOME is not defined.");
|
||||
dir += "/Library/Application Support";
|
||||
#else
|
||||
dir = qgetenv ("XDG_CONFIG_HOME");
|
||||
if (dir.isEmpty())
|
||||
dir = qgetenv ("HOME");
|
||||
if (dir.isEmpty())
|
||||
throw Exception("neither $XDG_CONFIG_HOME nor $HOME are defined");
|
||||
dir += "/.config";
|
||||
#endif
|
||||
QString const folder = QDir(dir).absoluteFilePath(configFolder);
|
||||
QDir().mkpath(folder);
|
||||
|
||||
return folder;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return user configuration directory used by bridge (based on Golang OS/File's UserCacheDir).
|
||||
//****************************************************************************************************************************************************
|
||||
QString userCacheDir()
|
||||
{
|
||||
QString dir;
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
dir = qgetenv ("LocalAppData");
|
||||
if (dir.isEmpty())
|
||||
throw Exception("%LocalAppData% is not defined.");
|
||||
#elif defined(Q_OS_IOS) || defined(Q_OS_DARWIN)
|
||||
dir = qgetenv ("HOME");
|
||||
if (dir.isEmpty())
|
||||
throw Exception("$HOME is not defined.");
|
||||
dir += "/Library/Caches";
|
||||
#else
|
||||
dir = qgetenv ("XDG_CACHE_HOME");
|
||||
if (dir.isEmpty())
|
||||
dir = qgetenv ("HOME");
|
||||
if (dir.isEmpty())
|
||||
throw Exception("neither XDG_CACHE_HOME nor $HOME are defined");
|
||||
dir += "/.cache";
|
||||
#endif
|
||||
|
||||
QString const folder = QDir(dir).absoluteFilePath(configFolder);
|
||||
QDir().mkpath(folder);
|
||||
|
||||
return folder;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return The value GOOS would return for the current platform.
|
||||
//****************************************************************************************************************************************************
|
||||
QString goos()
|
||||
{
|
||||
#if defined(Q_OS_DARWIN)
|
||||
return "darwin";
|
||||
#elif defined(Q_OS_WINDOWS)
|
||||
return "windows";
|
||||
#else
|
||||
return "linux";
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// Slow, but not biased. Not for use in crypto functions though, as the RNG use std::random_device as a seed.
|
||||
///
|
||||
/// \return a random number in the range [0, n-1]
|
||||
//****************************************************************************************************************************************************
|
||||
qint64 randN(qint64 n)
|
||||
{
|
||||
QMutexLocker locker(&rngMutex);
|
||||
return (n > 0) ? std::uniform_int_distribution<qint64>(0, n - 1)(rng()) : 0;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return A random first name.
|
||||
//****************************************************************************************************************************************************
|
||||
QString randomFirstName()
|
||||
{
|
||||
return firstNames[randN(firstNames.size())];
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return A random last name.
|
||||
//****************************************************************************************************************************************************
|
||||
QString randomLastName()
|
||||
{
|
||||
return lastNames[randN(lastNames.size())];
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
//
|
||||
//****************************************************************************************************************************************************
|
||||
SPUser randomUser()
|
||||
{
|
||||
SPUser user = User::newUser(nullptr);
|
||||
user->setID(QUuid::createUuid().toString());
|
||||
QString const firstName = randomFirstName();
|
||||
QString const lastName = randomLastName();
|
||||
QString const username = QString("%1.%2").arg(firstName.toLower(), lastName.toLower());
|
||||
user->setUsername(username);
|
||||
user->setAddresses(QStringList() << (username + "@proton.me") << (username + "@protonmail.com") );
|
||||
user->setPassword(QUuid().createUuid().toString(QUuid::StringFormat::WithoutBraces).left(20));
|
||||
user->setAvatarText(firstName.left(1) + lastName.left(1));
|
||||
user->setLoggedIn(true);
|
||||
user->setSplitMode(false);
|
||||
user->setSetupGuideSeen(true);
|
||||
qint64 const totalBytes = (500 + randN(2501)) * 1000000;
|
||||
user->setUsedBytes(float(bridgepp::randN(totalBytes + 1)) * 1.05f); // we maybe slightly over quota
|
||||
user->setTotalBytes(float(totalBytes));
|
||||
return user;
|
||||
}
|
||||
|
||||
|
||||
} // namespace bridgepp
|
||||
@ -1,42 +0,0 @@
|
||||
// Copyright (c) 2022 Proton AG
|
||||
//
|
||||
// This file is part of Proton Mail Bridge.
|
||||
//
|
||||
// Proton Mail Bridge is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Proton Mail Bridge is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
#ifndef BRIDGE_PP_TESTER_BRIDGE_UTILS_H
|
||||
#define BRIDGE_PP_TESTER_BRIDGE_UTILS_H
|
||||
|
||||
|
||||
#include <bridgepp/User/User.h>
|
||||
|
||||
|
||||
namespace bridgepp
|
||||
{
|
||||
|
||||
|
||||
QString userConfigDir(); ///< Get the path of the user configuration folder.
|
||||
QString userCacheDir(); ///< Get the path of the user cache folder.
|
||||
QString goos(); ///< return the value of Go's GOOS for the current platform ("darwin", "linux" and "windows" are supported).
|
||||
qint64 randN(qint64 n); ///< return a random integer in the half open range [0,n)
|
||||
QString randomFirstName(); ///< Get a random first name from a pre-determined list.
|
||||
QString randomLastName(); ///< Get a random first name from a pre-determined list.
|
||||
SPUser randomUser(); ///< Get a random user.
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
#endif // BRIDGE_PP_TESTER_BRIDGE_UTILS_H
|
||||
@ -1,74 +0,0 @@
|
||||
// Copyright (c) 2022 Proton AG
|
||||
//
|
||||
// This file is part of Proton Mail Bridge.
|
||||
//
|
||||
// Proton Mail Bridge is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Proton Mail Bridge is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
#include "Exception.h"
|
||||
|
||||
|
||||
namespace bridgepp
|
||||
{
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] what A description of the exception
|
||||
//****************************************************************************************************************************************************
|
||||
Exception::Exception(QString what) noexcept
|
||||
: std::exception()
|
||||
, what_(std::move(what))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] ref The Exception to copy from
|
||||
//****************************************************************************************************************************************************
|
||||
Exception::Exception(Exception const& ref) noexcept
|
||||
: std::exception(ref)
|
||||
, what_(ref.what_)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] ref The Exception to copy from
|
||||
//****************************************************************************************************************************************************
|
||||
Exception::Exception(Exception&& ref) noexcept
|
||||
: std::exception(ref)
|
||||
, what_(ref.what_)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return a string describing the exception
|
||||
//****************************************************************************************************************************************************
|
||||
QString const& Exception::qwhat() const noexcept
|
||||
{
|
||||
return what_;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return A pointer to the description string of the exception.
|
||||
//****************************************************************************************************************************************************
|
||||
const char* Exception::what() const noexcept
|
||||
{
|
||||
return what_.toLocal8Bit().constData();
|
||||
}
|
||||
|
||||
|
||||
} // namespace bridgepp
|
||||
@ -1,53 +0,0 @@
|
||||
// Copyright (c) 2022 Proton AG
|
||||
//
|
||||
// This file is part of Proton Mail Bridge.
|
||||
//
|
||||
// Proton Mail Bridge is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Proton Mail Bridge is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
#ifndef BRIDGE_PP_EXCEPTION_H
|
||||
#define BRIDGE_PP_EXCEPTION_H
|
||||
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
|
||||
namespace bridgepp
|
||||
{
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \brief Exception class.
|
||||
//****************************************************************************************************************************************************
|
||||
class Exception : public std::exception
|
||||
{
|
||||
public: // member functions
|
||||
explicit Exception(QString what = QString()) noexcept; ///< Constructor
|
||||
Exception(Exception const &ref) noexcept; ///< copy constructor
|
||||
Exception(Exception &&ref) noexcept; ///< copy constructor
|
||||
Exception &operator=(Exception const &) = delete; ///< Disabled assignment operator
|
||||
Exception &operator=(Exception &&) = delete; ///< Disabled assignment operator
|
||||
~Exception() noexcept override = default; ///< Destructor
|
||||
QString const &qwhat() const noexcept; ///< Return the description of the exception as a QString
|
||||
const char *what() const noexcept override; ///< Return the description of the exception as C style string
|
||||
|
||||
private: // data members
|
||||
QString const what_; ///< The description of the exception
|
||||
};
|
||||
|
||||
|
||||
} // namespace bridgepp
|
||||
|
||||
|
||||
#endif //BRIDGE_PP_EXCEPTION_H
|
||||
@ -1,620 +0,0 @@
|
||||
// Copyright (c) 2022 Proton AG
|
||||
//
|
||||
// This file is part of Proton Mail Bridge.
|
||||
//
|
||||
// Proton Mail Bridge is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Proton Mail Bridge is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
#include "EventFactory.h"
|
||||
|
||||
|
||||
namespace bridgepp
|
||||
{
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return a new SPStreamEvent
|
||||
//****************************************************************************************************************************************************
|
||||
bridgepp::SPStreamEvent newStreamEvent()
|
||||
{
|
||||
return std::make_shared<grpc::StreamEvent>();
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] appEvent The app event.
|
||||
/// \return The stream event.
|
||||
//****************************************************************************************************************************************************
|
||||
bridgepp::SPStreamEvent wrapAppEvent(grpc::AppEvent *appEvent)
|
||||
{
|
||||
auto event = newStreamEvent();
|
||||
event->set_allocated_app(appEvent);
|
||||
return event;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] loginEvent The login event.
|
||||
/// \return The stream event.
|
||||
//****************************************************************************************************************************************************
|
||||
bridgepp::SPStreamEvent wrapLoginEvent(grpc::LoginEvent *loginEvent)
|
||||
{
|
||||
auto event = newStreamEvent();
|
||||
event->set_allocated_login(loginEvent);
|
||||
return event;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] updateEvent The app event.
|
||||
/// \return The stream event.
|
||||
//****************************************************************************************************************************************************
|
||||
bridgepp::SPStreamEvent wrapUpdateEvent(grpc::UpdateEvent *updateEvent)
|
||||
{
|
||||
auto event = newStreamEvent();
|
||||
event->set_allocated_update(updateEvent);
|
||||
return event;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] cacheEvent The cache event.
|
||||
/// \return The stream event.
|
||||
//****************************************************************************************************************************************************
|
||||
bridgepp::SPStreamEvent wrapCacheEvent(grpc::CacheEvent *cacheEvent)
|
||||
{
|
||||
auto event = newStreamEvent();
|
||||
event->set_allocated_cache(cacheEvent);
|
||||
return event;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] mailSettingsEvent The mail settings event.
|
||||
/// \return The stream event.
|
||||
//****************************************************************************************************************************************************
|
||||
bridgepp::SPStreamEvent wrapMailSettingsEvent(grpc::MailSettingsEvent *mailSettingsEvent)
|
||||
{
|
||||
auto event = newStreamEvent();
|
||||
event->set_allocated_mailsettings(mailSettingsEvent);
|
||||
return event;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] keychainEvent The keychain event.
|
||||
/// \return The stream event.
|
||||
//****************************************************************************************************************************************************
|
||||
bridgepp::SPStreamEvent wrapKeychainEvent(grpc::KeychainEvent *keychainEvent)
|
||||
{
|
||||
auto event = newStreamEvent();
|
||||
event->set_allocated_keychain(keychainEvent);
|
||||
return event;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] mailEvent The mail event.
|
||||
/// \return The stream event.
|
||||
//****************************************************************************************************************************************************
|
||||
bridgepp::SPStreamEvent wrapMailEvent(grpc::MailEvent *mailEvent)
|
||||
{
|
||||
auto event = newStreamEvent();
|
||||
event->set_allocated_mail(mailEvent);
|
||||
return event;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] userEvent The user event.
|
||||
/// \return The stream event.
|
||||
//****************************************************************************************************************************************************
|
||||
bridgepp::SPStreamEvent wrapUserEvent(grpc::UserEvent *userEvent)
|
||||
{
|
||||
auto event = newStreamEvent();
|
||||
event->set_allocated_user(userEvent);
|
||||
return event;
|
||||
}
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] connected The internet status.
|
||||
/// \return The event.
|
||||
//****************************************************************************************************************************************************
|
||||
SPStreamEvent newInternetStatusEvent(bool connected)
|
||||
{
|
||||
auto *internetStatusEvent = new grpc::InternetStatusEvent();
|
||||
internetStatusEvent->set_connected(connected);
|
||||
auto appEvent = new grpc::AppEvent;
|
||||
appEvent->set_allocated_internetstatus(internetStatusEvent);
|
||||
return wrapAppEvent(appEvent);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return The event.
|
||||
//****************************************************************************************************************************************************
|
||||
SPStreamEvent newToggleAutostartFinishedEvent()
|
||||
{
|
||||
auto *event = new grpc::ToggleAutostartFinishedEvent;
|
||||
auto appEvent = new grpc::AppEvent;
|
||||
appEvent->set_allocated_toggleautostartfinished(event);
|
||||
return wrapAppEvent(appEvent);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return The event.
|
||||
//****************************************************************************************************************************************************
|
||||
SPStreamEvent newResetFinishedEvent()
|
||||
{
|
||||
auto event = new grpc::ResetFinishedEvent;
|
||||
auto appEvent = new grpc::AppEvent;
|
||||
appEvent->set_allocated_resetfinished(event);
|
||||
return wrapAppEvent(appEvent);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return The event.
|
||||
//****************************************************************************************************************************************************
|
||||
SPStreamEvent newReportBugFinishedEvent()
|
||||
{
|
||||
auto event = new grpc::ReportBugFinishedEvent;
|
||||
auto appEvent = new grpc::AppEvent;
|
||||
appEvent->set_allocated_reportbugfinished(event);
|
||||
return wrapAppEvent(appEvent);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return The event.
|
||||
//****************************************************************************************************************************************************
|
||||
SPStreamEvent newReportBugSuccessEvent()
|
||||
{
|
||||
auto event = new grpc::ReportBugSuccessEvent;
|
||||
auto appEvent = new grpc::AppEvent;
|
||||
appEvent->set_allocated_reportbugsuccess(event);
|
||||
return wrapAppEvent(appEvent);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return The event.
|
||||
//****************************************************************************************************************************************************
|
||||
SPStreamEvent newReportBugErrorEvent()
|
||||
{
|
||||
auto event = new grpc::ReportBugErrorEvent;
|
||||
auto appEvent = new grpc::AppEvent;
|
||||
appEvent->set_allocated_reportbugerror(event);
|
||||
return wrapAppEvent(appEvent);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return The event.
|
||||
//****************************************************************************************************************************************************
|
||||
SPStreamEvent newShowMainWindowEvent()
|
||||
{
|
||||
auto event = new grpc::ShowMainWindowEvent;
|
||||
auto appEvent = new grpc::AppEvent;
|
||||
appEvent->set_allocated_showmainwindow(event);
|
||||
return wrapAppEvent(appEvent);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] error The error.
|
||||
/// \param[in] message The message.
|
||||
/// \return The event.
|
||||
//****************************************************************************************************************************************************
|
||||
SPStreamEvent newLoginError(grpc::LoginErrorType error, QString const &message)
|
||||
{
|
||||
auto event = new ::grpc::LoginErrorEvent;
|
||||
event->set_type(error);
|
||||
event->set_message(message.toStdString());
|
||||
auto loginEvent = new grpc::LoginEvent;
|
||||
loginEvent->set_allocated_error(event);
|
||||
return wrapLoginEvent(loginEvent);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] username The username.
|
||||
/// \return The event.
|
||||
//****************************************************************************************************************************************************
|
||||
SPStreamEvent newLoginTfaRequestedEvent(QString const &username)
|
||||
{
|
||||
auto event = new ::grpc::LoginTfaRequestedEvent;
|
||||
event->set_username(username.toStdString());
|
||||
auto loginEvent = new grpc::LoginEvent;
|
||||
loginEvent->set_allocated_tfarequested(event);
|
||||
return wrapLoginEvent(loginEvent);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] username The username.
|
||||
/// \return The event.
|
||||
//****************************************************************************************************************************************************
|
||||
SPStreamEvent newLoginTwoPasswordsRequestedEvent()
|
||||
{
|
||||
auto event = new ::grpc::LoginTwoPasswordsRequestedEvent;
|
||||
auto loginEvent = new grpc::LoginEvent;
|
||||
loginEvent->set_allocated_twopasswordrequested(event);
|
||||
return wrapLoginEvent(loginEvent);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] userID The userID.
|
||||
/// \return The event.
|
||||
//****************************************************************************************************************************************************
|
||||
SPStreamEvent newLoginFinishedEvent(QString const &userID)
|
||||
{
|
||||
auto event = new ::grpc::LoginFinishedEvent;
|
||||
event->set_userid(userID.toStdString());
|
||||
auto loginEvent = new grpc::LoginEvent;
|
||||
loginEvent->set_allocated_finished(event);
|
||||
return wrapLoginEvent(loginEvent);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] userID The userID.
|
||||
/// \return The event.
|
||||
//****************************************************************************************************************************************************
|
||||
SPStreamEvent newLoginAlreadyLoggedInEvent(QString const &userID)
|
||||
{
|
||||
auto event = new ::grpc::LoginFinishedEvent;
|
||||
event->set_userid(userID.toStdString());
|
||||
auto loginEvent = new grpc::LoginEvent;
|
||||
loginEvent->set_allocated_alreadyloggedin(event);
|
||||
return wrapLoginEvent(loginEvent);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] errorType The error type.
|
||||
/// \return The event.
|
||||
//****************************************************************************************************************************************************
|
||||
SPStreamEvent newUpdateErrorEvent(grpc::UpdateErrorType errorType)
|
||||
{
|
||||
auto event = new grpc::UpdateErrorEvent;
|
||||
event->set_type(errorType);
|
||||
auto updateEvent = new grpc::UpdateEvent;
|
||||
updateEvent->set_allocated_error(event);
|
||||
return wrapUpdateEvent(updateEvent);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] version The version.
|
||||
/// \return The event.
|
||||
//****************************************************************************************************************************************************
|
||||
SPStreamEvent newUpdateManualReadyEvent(QString const &version)
|
||||
{
|
||||
auto event = new grpc::UpdateManualReadyEvent;
|
||||
event->set_version(version.toStdString());
|
||||
auto updateEvent = new grpc::UpdateEvent;
|
||||
updateEvent->set_allocated_manualready(event);
|
||||
return wrapUpdateEvent(updateEvent);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return the event.
|
||||
//****************************************************************************************************************************************************
|
||||
SPStreamEvent newUpdateManualRestartNeededEvent()
|
||||
{
|
||||
auto event = new grpc::UpdateManualRestartNeededEvent;
|
||||
auto updateEvent = new grpc::UpdateEvent;
|
||||
updateEvent->set_allocated_manualrestartneeded(event);
|
||||
return wrapUpdateEvent(updateEvent);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] version The version.
|
||||
/// \return The event.
|
||||
//****************************************************************************************************************************************************
|
||||
SPStreamEvent newUpdateForceEvent(QString const &version)
|
||||
{
|
||||
auto event = new grpc::UpdateForceEvent;
|
||||
event->set_version(version.toStdString());
|
||||
auto updateEvent = new grpc::UpdateEvent;
|
||||
updateEvent->set_allocated_force(event);
|
||||
return wrapUpdateEvent(updateEvent);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return the event.
|
||||
//****************************************************************************************************************************************************
|
||||
SPStreamEvent newUpdateSilentRestartNeeded()
|
||||
{
|
||||
auto event = new grpc::UpdateSilentRestartNeeded;
|
||||
auto updateEvent = new grpc::UpdateEvent;
|
||||
updateEvent->set_allocated_silentrestartneeded(event);
|
||||
return wrapUpdateEvent(updateEvent);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return The event.
|
||||
//****************************************************************************************************************************************************
|
||||
SPStreamEvent newUpdateIsLatestVersion()
|
||||
{
|
||||
auto event = new grpc::UpdateIsLatestVersion;
|
||||
auto updateEvent = new grpc::UpdateEvent;
|
||||
updateEvent->set_allocated_islatestversion(event);
|
||||
return wrapUpdateEvent(updateEvent);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return The event.
|
||||
//****************************************************************************************************************************************************
|
||||
SPStreamEvent newUpdateCheckFinished()
|
||||
{
|
||||
auto event = new grpc::UpdateCheckFinished;
|
||||
auto updateEvent = new grpc::UpdateEvent;
|
||||
updateEvent->set_allocated_checkfinished(event);
|
||||
return wrapUpdateEvent(updateEvent);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] errorType The error type.
|
||||
/// \return The event.
|
||||
//****************************************************************************************************************************************************
|
||||
SPStreamEvent newCacheErrorEvent(grpc::CacheErrorType errorType)
|
||||
{
|
||||
auto event = new grpc::CacheErrorEvent;
|
||||
event->set_type(errorType);
|
||||
auto cacheEvent = new grpc::CacheEvent;
|
||||
cacheEvent->set_allocated_error(event);
|
||||
return wrapCacheEvent(cacheEvent);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return The event.
|
||||
//****************************************************************************************************************************************************
|
||||
SPStreamEvent newCacheLocationChangeSuccessEvent()
|
||||
{
|
||||
auto event = new grpc::CacheLocationChangeSuccessEvent;
|
||||
auto cacheEvent = new grpc::CacheEvent;
|
||||
cacheEvent->set_allocated_locationchangedsuccess(event);
|
||||
return wrapCacheEvent(cacheEvent);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return The event.
|
||||
//****************************************************************************************************************************************************
|
||||
SPStreamEvent newChangeLocalCacheFinishedEvent()
|
||||
{
|
||||
auto event = new grpc::ChangeLocalCacheFinishedEvent;
|
||||
auto cacheEvent = new grpc::CacheEvent;
|
||||
cacheEvent->set_allocated_changelocalcachefinished(event);
|
||||
return wrapCacheEvent(cacheEvent);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] enabled The new state of the cache.
|
||||
/// \return The event.
|
||||
//****************************************************************************************************************************************************
|
||||
SPStreamEvent newIsCacheOnDiskEnabledChanged(bool enabled)
|
||||
{
|
||||
auto event = new grpc::IsCacheOnDiskEnabledChanged;
|
||||
event->set_enabled(enabled);
|
||||
auto cacheEvent = new grpc::CacheEvent;
|
||||
cacheEvent->set_allocated_iscacheondiskenabledchanged(event);
|
||||
return wrapCacheEvent(cacheEvent);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] path The path of the cache.
|
||||
/// \return The event.
|
||||
//****************************************************************************************************************************************************
|
||||
SPStreamEvent newDiskCachePathChanged(QString const &path)
|
||||
{
|
||||
auto event = new grpc::DiskCachePathChanged;
|
||||
event->set_path(path.toStdString());
|
||||
auto cacheEvent = new grpc::CacheEvent;
|
||||
cacheEvent->set_allocated_diskcachepathchanged(event);
|
||||
return wrapCacheEvent(cacheEvent);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] errorType The error type.
|
||||
/// \return The event.
|
||||
//****************************************************************************************************************************************************
|
||||
SPStreamEvent newMailSettingsErrorEvent(grpc::MailSettingsErrorType errorType)
|
||||
{
|
||||
auto event = new grpc::MailSettingsErrorEvent;
|
||||
event->set_type(errorType);
|
||||
auto mailSettingsEvent = new grpc::MailSettingsEvent;
|
||||
mailSettingsEvent->set_allocated_error(event);
|
||||
return wrapMailSettingsEvent(mailSettingsEvent);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return The event.
|
||||
//****************************************************************************************************************************************************
|
||||
SPStreamEvent newUseSslForSmtpFinishedEvent()
|
||||
{
|
||||
auto event = new grpc::UseSslForSmtpFinishedEvent;
|
||||
auto mailSettingsEvent = new grpc::MailSettingsEvent;
|
||||
mailSettingsEvent->set_allocated_usesslforsmtpfinished(event);
|
||||
return wrapMailSettingsEvent(mailSettingsEvent);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return The event.
|
||||
//****************************************************************************************************************************************************
|
||||
SPStreamEvent newChangePortsFinishedEvent()
|
||||
{
|
||||
auto event = new grpc::ChangePortsFinishedEvent;
|
||||
auto mailSettingsEvent = new grpc::MailSettingsEvent;
|
||||
mailSettingsEvent->set_allocated_changeportsfinished(event);
|
||||
return wrapMailSettingsEvent(mailSettingsEvent);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return The event.
|
||||
//****************************************************************************************************************************************************
|
||||
SPStreamEvent newChangeKeychainFinishedEvent()
|
||||
{
|
||||
auto event = new grpc::ChangeKeychainFinishedEvent;
|
||||
auto keychainEvent = new grpc::KeychainEvent;
|
||||
keychainEvent->set_allocated_changekeychainfinished(event);
|
||||
return wrapKeychainEvent(keychainEvent);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return The event.
|
||||
//****************************************************************************************************************************************************
|
||||
SPStreamEvent newHasNoKeychainEvent()
|
||||
{
|
||||
auto event = new grpc::HasNoKeychainEvent;
|
||||
auto keychainEvent = new grpc::KeychainEvent;
|
||||
keychainEvent->set_allocated_hasnokeychain(event);
|
||||
return wrapKeychainEvent(keychainEvent);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return The event.
|
||||
//****************************************************************************************************************************************************
|
||||
SPStreamEvent newRebuildKeychainEvent()
|
||||
{
|
||||
auto event = new grpc::RebuildKeychainEvent;
|
||||
auto keychainEvent = new grpc::KeychainEvent;
|
||||
keychainEvent->set_allocated_rebuildkeychain(event);
|
||||
return wrapKeychainEvent(keychainEvent);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] email The email.
|
||||
/// \return The event.
|
||||
//****************************************************************************************************************************************************
|
||||
SPStreamEvent newNoActiveKeyForRecipientEvent(QString const &email)
|
||||
{
|
||||
auto event = new grpc::NoActiveKeyForRecipientEvent;
|
||||
event->set_email(email.toStdString());
|
||||
auto mailEvent = new grpc::MailEvent;
|
||||
mailEvent->set_allocated_noactivekeyforrecipientevent(event);
|
||||
return wrapMailEvent(mailEvent);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] address The address.
|
||||
/// /// \return The event.
|
||||
//****************************************************************************************************************************************************
|
||||
SPStreamEvent newAddressChangedEvent(QString const &address)
|
||||
{
|
||||
auto event = new grpc::AddressChangedEvent;
|
||||
event->set_address(address.toStdString());
|
||||
auto mailEvent = new grpc::MailEvent;
|
||||
mailEvent->set_allocated_addresschanged(event);
|
||||
return wrapMailEvent(mailEvent);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] address The address.
|
||||
/// \return The event.
|
||||
//****************************************************************************************************************************************************
|
||||
SPStreamEvent newAddressChangedLogoutEvent(QString const &address)
|
||||
{
|
||||
auto event = new grpc::AddressChangedLogoutEvent;
|
||||
event->set_address(address.toStdString());
|
||||
auto mailEvent = new grpc::MailEvent;
|
||||
mailEvent->set_allocated_addresschangedlogout(event);
|
||||
return wrapMailEvent(mailEvent);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return The event.
|
||||
//****************************************************************************************************************************************************
|
||||
SPStreamEvent newApiCertIssueEvent()
|
||||
{
|
||||
auto event = new grpc::ApiCertIssueEvent;
|
||||
auto mailEvent = new grpc::MailEvent;
|
||||
mailEvent->set_allocated_apicertissue(event);
|
||||
return wrapMailEvent(mailEvent);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] userID The userID.
|
||||
/// \return The event.
|
||||
//****************************************************************************************************************************************************
|
||||
SPStreamEvent newToggleSplitModeFinishedEvent(QString const &userID)
|
||||
{
|
||||
auto event = new grpc::ToggleSplitModeFinishedEvent;
|
||||
event->set_userid(userID.toStdString());
|
||||
auto userEvent = new grpc::UserEvent;
|
||||
userEvent->set_allocated_togglesplitmodefinished(event);
|
||||
return wrapUserEvent(userEvent);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] username The username.
|
||||
/// /// \return The event.
|
||||
//****************************************************************************************************************************************************
|
||||
SPStreamEvent newUserDisconnectedEvent(QString const &username)
|
||||
{
|
||||
auto event = new grpc::UserDisconnectedEvent;
|
||||
event->set_username(username.toStdString());
|
||||
auto userEvent = new grpc::UserEvent;
|
||||
userEvent->set_allocated_userdisconnected(event);
|
||||
return wrapUserEvent(userEvent);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] userID The userID.
|
||||
/// \return The event.
|
||||
//****************************************************************************************************************************************************
|
||||
SPStreamEvent newUserChangedEvent(QString const &userID)
|
||||
{
|
||||
auto event = new grpc::UserChangedEvent;
|
||||
event->set_userid(userID.toStdString());
|
||||
auto userEvent = new grpc::UserEvent;
|
||||
userEvent->set_allocated_userchanged(event);
|
||||
return wrapUserEvent(userEvent);
|
||||
}
|
||||
|
||||
|
||||
} // namespace bridgepp
|
||||
@ -1,88 +0,0 @@
|
||||
// Copyright (c) 2022 Proton AG
|
||||
//
|
||||
// This file is part of Proton Mail Bridge.
|
||||
//
|
||||
// Proton Mail Bridge is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Proton Mail Bridge is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
#ifndef BRIDGE_PP_EVENT_FACTORY_H
|
||||
#define BRIDGE_PP_EVENT_FACTORY_H
|
||||
|
||||
|
||||
#include "bridge.grpc.pb.h"
|
||||
#include "GRPCUtils.h"
|
||||
|
||||
|
||||
namespace bridgepp
|
||||
{
|
||||
|
||||
|
||||
// App events
|
||||
SPStreamEvent newInternetStatusEvent(bool connected); ///< Create a new InternetStatusEvent event.
|
||||
SPStreamEvent newToggleAutostartFinishedEvent(); ///< Create a new ToggleAutostartFinishedEvent event.
|
||||
SPStreamEvent newResetFinishedEvent(); ///< Create a new ResetFinishedEvent event.
|
||||
SPStreamEvent newReportBugFinishedEvent(); ///< Create a new ReportBugFinishedEvent event.
|
||||
SPStreamEvent newReportBugSuccessEvent(); ///< Create a new ReportBugSuccessEvent event.
|
||||
SPStreamEvent newReportBugErrorEvent(); ///< Create a new ReportBugErrorEvent event.
|
||||
SPStreamEvent newShowMainWindowEvent(); ///< Create a new ShowMainWindowEvent event.
|
||||
|
||||
// Login events
|
||||
SPStreamEvent newLoginError(grpc::LoginErrorType error, QString const &message); ///< Create a new LoginError event.
|
||||
SPStreamEvent newLoginTfaRequestedEvent(QString const &username); ///< Create a new LoginTfaRequestedEvent event.
|
||||
SPStreamEvent newLoginTwoPasswordsRequestedEvent(); ///< Create a new LoginTwoPasswordsRequestedEvent event.
|
||||
SPStreamEvent newLoginFinishedEvent(QString const &userID); ///< Create a new LoginFinishedEvent event.
|
||||
SPStreamEvent newLoginAlreadyLoggedInEvent(QString const &userID); ///< Create a new LoginAlreadyLoggedInEvent event.
|
||||
|
||||
// Update related events
|
||||
SPStreamEvent newUpdateErrorEvent(grpc::UpdateErrorType errorType); ///< Create a new UpdateErrorEvent event.
|
||||
SPStreamEvent newUpdateManualReadyEvent(QString const &version); ///< Create a new UpdateManualReadyEvent event.
|
||||
SPStreamEvent newUpdateManualRestartNeededEvent(); ///< Create a new UpdateManualRestartNeededEvent event.
|
||||
SPStreamEvent newUpdateForceEvent(QString const &version); ///< Create a new UpdateForceEvent event.
|
||||
SPStreamEvent newUpdateSilentRestartNeeded(); ///< Create a new UpdateSilentRestartNeeded event.
|
||||
SPStreamEvent newUpdateIsLatestVersion(); ///< Create a new UpdateIsLatestVersion event.
|
||||
SPStreamEvent newUpdateCheckFinished(); ///< Create a new UpdateCheckFinished event.
|
||||
|
||||
// Cache on disk related events
|
||||
SPStreamEvent newCacheErrorEvent(grpc::CacheErrorType errorType); ///< Create a new CacheErrorEvent event.
|
||||
SPStreamEvent newCacheLocationChangeSuccessEvent(); ///< Create a new CacheLocationChangeSuccessEvent event.
|
||||
SPStreamEvent newChangeLocalCacheFinishedEvent(); ///< Create a new ChangeLocalCacheFinishedEvent event.
|
||||
SPStreamEvent newIsCacheOnDiskEnabledChanged(bool enabled); ///< Create a new IsCacheOnDiskEnabledChanged event.
|
||||
SPStreamEvent newDiskCachePathChanged(QString const &path); ///< Create a new DiskCachePathChanged event.
|
||||
|
||||
// Mail settings related events
|
||||
SPStreamEvent newMailSettingsErrorEvent(grpc::MailSettingsErrorType errorType); ///< Create a new MailSettingsErrorEvent event.
|
||||
SPStreamEvent newUseSslForSmtpFinishedEvent(); ///< Create a new UseSslForSmtpFinishedEvent event.
|
||||
SPStreamEvent newChangePortsFinishedEvent(); ///< Create a new ChangePortsFinishedEvent event.
|
||||
|
||||
// keychain related events
|
||||
SPStreamEvent newChangeKeychainFinishedEvent(); ///< Create a new ChangeKeychainFinishedEvent event.
|
||||
SPStreamEvent newHasNoKeychainEvent(); ///< Create a new HasNoKeychainEvent event.
|
||||
SPStreamEvent newRebuildKeychainEvent(); ///< Create a new RebuildKeychainEvent event.
|
||||
|
||||
// Mail related events
|
||||
SPStreamEvent newNoActiveKeyForRecipientEvent(QString const &email); ///< Create a new NoActiveKeyForRecipientEvent event.
|
||||
SPStreamEvent newAddressChangedEvent(QString const &address); ///< Create a new AddressChangedEvent event.
|
||||
SPStreamEvent newAddressChangedLogoutEvent(QString const &address); ///< Create a new AddressChangedLogoutEvent event.
|
||||
SPStreamEvent newApiCertIssueEvent(); ///< Create a new ApiCertIssueEvent event.
|
||||
|
||||
// User list related event
|
||||
SPStreamEvent newToggleSplitModeFinishedEvent(QString const &userID); ///< Create a new ToggleSplitModeFinishedEvent event.
|
||||
SPStreamEvent newUserDisconnectedEvent(QString const &username); ///< Create a new UserDisconnectedEvent event.
|
||||
SPStreamEvent newUserChangedEvent(QString const &userID); ///< Create a new UserChangedEvent event.
|
||||
|
||||
|
||||
} // namespace bridgepp
|
||||
|
||||
|
||||
#endif //BRIDGE_PP_EVENT_FACTORY_H
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,243 +0,0 @@
|
||||
// Copyright (c) 2022 Proton AG
|
||||
//
|
||||
// This file is part of Proton Mail Bridge.
|
||||
//
|
||||
// Proton Mail Bridge is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Proton Mail Bridge is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
#ifndef BRIDGE_PP_RPC_CLIENT_H
|
||||
#define BRIDGE_PP_RPC_CLIENT_H
|
||||
|
||||
|
||||
#include "../User/User.h"
|
||||
#include "../Log/Log.h"
|
||||
#include "bridge.grpc.pb.h"
|
||||
#include "grpc++/grpc++.h"
|
||||
|
||||
|
||||
namespace bridgepp
|
||||
{
|
||||
|
||||
|
||||
typedef grpc::Status (grpc::Bridge::Stub::*SimpleMethod)(grpc::ClientContext *, const google::protobuf::Empty &, google::protobuf::Empty *);
|
||||
typedef grpc::Status (grpc::Bridge::Stub::*BoolSetter)(grpc::ClientContext *, const google::protobuf::BoolValue &, google::protobuf::Empty *);
|
||||
typedef grpc::Status (grpc::Bridge::Stub::*BoolGetter)(grpc::ClientContext *, const google::protobuf::Empty &, google::protobuf::BoolValue *);
|
||||
typedef grpc::Status (grpc::Bridge::Stub::*Int32Setter)(grpc::ClientContext *, const google::protobuf::Int32Value &, google::protobuf::Empty *);
|
||||
typedef grpc::Status (grpc::Bridge::Stub::*Int32Getter)(grpc::ClientContext *, const google::protobuf::Empty &, google::protobuf::Int32Value *);
|
||||
typedef grpc::Status (grpc::Bridge::Stub::*StringGetter)(grpc::ClientContext *, const google::protobuf::Empty &, google::protobuf::StringValue *);
|
||||
typedef grpc::Status (grpc::Bridge::Stub::*StringSetter)(grpc::ClientContext *, const google::protobuf::StringValue &, google::protobuf::Empty *);
|
||||
typedef grpc::Status (grpc::Bridge::Stub::*StringParamMethod)(grpc::ClientContext *, const google::protobuf::StringValue &, google::protobuf::Empty *);
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \brief gRPC client class. This class encapsulate the gRPC service, abstracting all data type conversions.
|
||||
//****************************************************************************************************************************************************
|
||||
class GRPCClient : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public: // member functions.
|
||||
GRPCClient() = default; ///< Default constructor.
|
||||
GRPCClient(GRPCClient const &) = delete; ///< Disabled copy-constructor.
|
||||
GRPCClient(GRPCClient &&) = delete; ///< Disabled assignment copy-constructor.
|
||||
~GRPCClient() override = default; ///< Destructor.
|
||||
GRPCClient &operator=(GRPCClient const &) = delete; ///< Disabled assignment operator.
|
||||
GRPCClient &operator=(GRPCClient &&) = delete; ///< Disabled move assignment operator.
|
||||
void setLog(Log *log); ///< Set the log for the client.
|
||||
bool connectToServer(QString &outError); ///< Establish connection to the gRPC server.
|
||||
|
||||
grpc::Status addLogEntry(Log::Level level, QString const &package, QString const &message); ///< Performs the "AddLogEntry" gRPC call.
|
||||
grpc::Status guiReady(); ///< performs the "GuiReady" gRPC call.
|
||||
grpc::Status isFirstGUIStart(bool &outIsFirst); ///< performs the "IsFirstGUIStart" gRPC call.
|
||||
grpc::Status isAutostartOn(bool &outIsOn); ///< Performs the "isAutostartOn" gRPC call.
|
||||
grpc::Status setIsAutostartOn(bool on); ///< Performs the "setIsAutostartOn" gRPC call.
|
||||
grpc::Status isBetaEnabled(bool &outEnabled); ///< Performs the "isBetaEnabled" gRPC call.
|
||||
grpc::Status setIsBetaEnabled(bool enabled); ///< Performs the 'setIsBetaEnabled' gRPC call.
|
||||
grpc::Status isAllMailVisible(bool &outIsVisible); ///< Performs the "isAllMailVisible" gRPC call.
|
||||
grpc::Status setIsAllMailVisible(bool isVisible); ///< Performs the 'setIsAllMailVisible' gRPC call.
|
||||
grpc::Status colorSchemeName(QString &outName); ///< Performs the "colorSchemeName' gRPC call.
|
||||
grpc::Status setColorSchemeName(QString const &name); ///< Performs the "setColorSchemeName' gRPC call.
|
||||
grpc::Status currentEmailClient(QString &outName); ///< Performs the 'currentEmailClient' gRPC call.
|
||||
grpc::Status reportBug(QString const &description, QString const &address, QString const &emailClient, bool includeLogs); ///< Performs the 'ReportBug' gRPC call.
|
||||
grpc::Status quit(); ///< Perform the "Quit" gRPC call.
|
||||
grpc::Status restart(); ///< Performs the Restart gRPC call.
|
||||
grpc::Status triggerReset(); ///< Performs the triggerReset gRPC call.
|
||||
grpc::Status forceLauncher(QString const &launcher); ///< Performs the 'ForceLauncher' call.
|
||||
grpc::Status setMainExecutable(QString const &exe); ///< Performs the 'SetMainExecutable' call.
|
||||
grpc::Status isPortFree(qint32 port, bool &outFree); ///< Performs the 'IsPortFree' call.
|
||||
grpc::Status showOnStartup(bool &outValue); ///< Performs the 'ShowOnStartup' call.
|
||||
grpc::Status showSplashScreen(bool &outValue); ///< Performs the 'ShowSplashScreen' call.
|
||||
grpc::Status goos(QString &outGoos); ///< Performs the 'GoOs' call.
|
||||
grpc::Status logsPath(QUrl &outPath); ///< Performs the 'LogsPath' call.
|
||||
grpc::Status licensePath(QUrl &outPath); ///< Performs the 'LicensePath' call.
|
||||
grpc::Status dependencyLicensesLink(QUrl &outUrl); ///< Performs the 'DependencyLicensesLink' call.
|
||||
grpc::Status version(QString &outVersion); ///< Performs the 'Version' call.
|
||||
grpc::Status releaseNotesPageLink(QUrl &outUrl); ///< Performs the 'releaseNotesPageLink' call.
|
||||
grpc::Status landingPageLink(QUrl &outUrl); ///< Performs the 'landingPageLink' call.
|
||||
grpc::Status hostname(QString &outHostname); ///< Performs the 'Hostname' call.
|
||||
|
||||
signals: // app related signals
|
||||
void internetStatus(bool isOn);
|
||||
void toggleAutostartFinished();
|
||||
void resetFinished();
|
||||
void reportBugFinished();
|
||||
void reportBugSuccess();
|
||||
void reportBugError();
|
||||
void showMainWindow();
|
||||
|
||||
// cache related calls
|
||||
public:
|
||||
grpc::Status isCacheOnDiskEnabled(bool &outEnabled); ///< Performs the 'isCacheOnDiskEnabled' call.
|
||||
grpc::Status diskCachePath(QUrl &outPath); ///< Performs the 'diskCachePath' call.
|
||||
grpc::Status changeLocalCache(bool enabled, QUrl const &path); ///< Performs the 'ChangeLocalCache' call.
|
||||
signals:
|
||||
void isCacheOnDiskEnabledChanged(bool enabled);
|
||||
void diskCachePathChanged(QUrl const &outPath);
|
||||
void cacheUnavailable(); // _ func() `signal:"cacheUnavailable"`
|
||||
void cacheCantMove(); // _ func() `signal:"cacheCantMove"`
|
||||
void cacheLocationChangeSuccess(); // _ func() `signal:"cacheLocationChangeSuccess"`
|
||||
void diskFull(); // _ func() `signal:"diskFull"`
|
||||
void changeLocalCacheFinished(bool willRestart); // _ func() `signal:"changeLocalCacheFinished"`
|
||||
|
||||
|
||||
// mail settings related calls
|
||||
public:
|
||||
grpc::Status useSSLForSMTP(bool &outUseSSL); ///< Performs the 'useSSLForSMTP' gRPC call
|
||||
grpc::Status setUseSSLForSMTP(bool useSSL); ///< Performs the 'currentEmailClient' gRPC call.
|
||||
grpc::Status portIMAP(int &outPort); ///< Performs the 'portImap' gRPC call.
|
||||
grpc::Status portSMTP(int &outPort); ///< Performs the 'portImap' gRPC call.
|
||||
grpc::Status changePorts(int portIMAP, int portSMTP); ///< Performs the 'changePorts' gRPC call.
|
||||
grpc::Status isDoHEnabled(bool &outEnabled); ///< Performs the 'isDoHEnabled' gRPC call.
|
||||
grpc::Status setIsDoHEnabled(bool enabled); ///< Performs the 'setIsDoHEnabled' gRPC call.
|
||||
|
||||
signals:
|
||||
void portIssueIMAP();
|
||||
void portIssueSMTP();
|
||||
void toggleUseSSLFinished();
|
||||
void changePortFinished();
|
||||
|
||||
public: // login related calls
|
||||
grpc::Status login(QString const &username, QString const &password); ///< Performs the 'login' call.
|
||||
grpc::Status login2FA(QString const &username, QString const &code); ///< Performs the 'login2FA' call.
|
||||
grpc::Status login2Passwords(QString const &username, QString const &password); ///< Performs the 'login2Passwords' call.
|
||||
grpc::Status loginAbort(QString const &username); ///< Performs the 'loginAbort' call.
|
||||
|
||||
signals:
|
||||
void loginUsernamePasswordError(QString const &errMsg); // _ func(errorMsg string) `signal:"loginUsernamePasswordError"`
|
||||
void loginFreeUserError(); // _ func() `signal:"loginFreeUserError"`
|
||||
void loginConnectionError(QString const &errMsg); // _ func(errorMsg string) `signal:"loginConnectionError"`
|
||||
void login2FARequested(QString const &userName); // _ func(username string) `signal:"login2FARequested"`
|
||||
void login2FAError(QString const &errMsg); // _ func(errorMsg string) `signal:"login2FAError"`
|
||||
void login2FAErrorAbort(QString const &errMsg); // _ func(errorMsg string) `signal:"login2FAErrorAbort"`
|
||||
void login2PasswordRequested(); // _ func() `signal:"login2PasswordRequested"`
|
||||
void login2PasswordError(QString const &errMsg); // _ func(errorMsg string) `signal:"login2PasswordError"`
|
||||
void login2PasswordErrorAbort(QString const &errMsg); // _ func(errorMsg string) `signal:"login2PasswordErrorAbort"`
|
||||
void loginFinished(QString const &userID); // _ func(index int) `signal:"loginFinished"`
|
||||
void loginAlreadyLoggedIn(QString const &userID); // _ func(index int) `signal:"loginAlreadyLoggedIn"`
|
||||
|
||||
public: // Update related calls
|
||||
grpc::Status checkUpdate();
|
||||
grpc::Status installUpdate();
|
||||
grpc::Status setIsAutomaticUpdateOn(bool on);
|
||||
grpc::Status isAutomaticUpdateOn(bool &isOn);
|
||||
|
||||
signals:
|
||||
void updateManualError();
|
||||
void updateForceError();
|
||||
void updateSilentError();
|
||||
void updateManualReady(QString const &version);
|
||||
void updateManualRestartNeeded();
|
||||
void updateForce(QString const &version);
|
||||
void updateSilentRestartNeeded();
|
||||
void updateIsLatestVersion();
|
||||
void checkUpdatesFinished();
|
||||
void updateVersionChanged();
|
||||
|
||||
public: // user related calls
|
||||
grpc::Status getUserList(QList<SPUser> &outUsers);
|
||||
grpc::Status getUser(QString const &userID, SPUser &outUser);
|
||||
grpc::Status logoutUser(QString const &userID); ///< Performs the 'logoutUser' call.
|
||||
grpc::Status removeUser(QString const &userID); ///< Performs the 'removeUser' call.
|
||||
grpc::Status configureAppleMail(QString const &userID, QString const &address); ///< Performs the 'configureAppleMail' call.
|
||||
grpc::Status setUserSplitMode(QString const &userID, bool active); ///< Performs the 'SetUserSplitMode' call.
|
||||
|
||||
signals:
|
||||
void toggleSplitModeFinished(QString const &userID);
|
||||
void userDisconnected(QString const &username);
|
||||
void userChanged(QString const &userID);
|
||||
|
||||
|
||||
public: // keychain related calls
|
||||
grpc::Status availableKeychains(QStringList &outKeychains);
|
||||
grpc::Status currentKeychain(QString &outKeychain);
|
||||
grpc::Status setCurrentKeychain(QString const &keychain);
|
||||
|
||||
signals:
|
||||
void changeKeychainFinished();
|
||||
void hasNoKeychain();
|
||||
void rebuildKeychain();
|
||||
void certIsReady();
|
||||
|
||||
signals: // mail related events
|
||||
void noActiveKeyForRecipient(QString const &email); // _ func(email string) `signal:noActiveKeyForRecipient`
|
||||
void addressChanged(QString const &address); // _ func(address string) `signal:addressChanged`
|
||||
void addressChangedLogout(QString const &address); // _ func(address string) `signal:addressChangedLogout`
|
||||
void apiCertIssue();
|
||||
|
||||
public:
|
||||
bool isEventStreamActive() const; ///< Check if the event stream is active.
|
||||
grpc::Status runEventStreamReader(); ///< Retrieve and signal the events in the event stream.
|
||||
grpc::Status stopEventStreamReader(); ///< Stop the event stream.
|
||||
|
||||
private slots:
|
||||
void configFolderChanged();
|
||||
|
||||
private:
|
||||
void logDebug(QString const &message); ///< Log an event.
|
||||
void logError(QString const &message); ///< Log an event.
|
||||
grpc::Status logGRPCCallStatus(grpc::Status const &status, QString const &callName, QList<grpc::StatusCode> allowedErrors = {}); ///< Log the status of a gRPC code.
|
||||
grpc::Status simpleMethod(SimpleMethod method); ///< perform a gRPC call to a bool setter.
|
||||
grpc::Status setBool(BoolSetter setter, bool value); ///< perform a gRPC call to a bool setter.
|
||||
grpc::Status getBool(BoolGetter getter, bool &outValue); ///< perform a gRPC call to a bool getter.
|
||||
grpc::Status setInt32(Int32Setter setter, int value); ///< perform a gRPC call to an int setter.
|
||||
grpc::Status getInt32(Int32Getter getter, int &outValue); ///< perform a gRPC call to an int getter.
|
||||
grpc::Status setString(StringSetter getter, QString const &value); ///< Perform a gRPC call to a string setter.
|
||||
grpc::Status getString(StringGetter getter, QString &outValue); ///< Perform a gRPC call to a string getter.
|
||||
grpc::Status getURLForLocalFile(StringGetter getter, QUrl &outValue); ///< Perform a gRPC call to a string getter, with resulted converted to QUrl for a local file path.
|
||||
grpc::Status getURL(StringGetter getter, QUrl &outValue); ///< Perform a gRPC call to a string getter, with resulted converted to QUrl.
|
||||
grpc::Status methodWithStringParam(StringParamMethod method, QString const &str); ///< Perform a gRPC call that takes a string as a parameter and returns an Empty.
|
||||
SPUser parseGRPCUser(grpc::User const &grpcUser); ///< Parse a gRPC user struct and return a User.
|
||||
|
||||
std::string getServerCertificate(); ///< Wait until server certificates is generated and retrieve it.
|
||||
void processAppEvent(grpc::AppEvent const &event); ///< Process an 'App' event.
|
||||
void processLoginEvent(grpc::LoginEvent const &event); ///< Process a 'Login' event.
|
||||
void processUpdateEvent(grpc::UpdateEvent const &event); ///< Process an 'Update' event.
|
||||
void processCacheEvent(grpc::CacheEvent const &event); ///< Process a 'Cache' event.
|
||||
void processMailSettingsEvent(grpc::MailSettingsEvent const &event); ///< Process a 'MailSettings' event.
|
||||
void processKeychainEvent(grpc::KeychainEvent const &event); ///< Process a 'Keychain' event.
|
||||
void processMailEvent(grpc::MailEvent const &event); ///< Process a 'Mail' event.
|
||||
void processUserEvent(grpc::UserEvent const &event); ///< Process a 'User' event.
|
||||
|
||||
private: // data members.
|
||||
Log *log_ { nullptr }; ///< The log for the GRPC client.
|
||||
std::shared_ptr<grpc::Channel> channel_ { nullptr }; ///< The gRPC channel.
|
||||
std::shared_ptr<grpc::Bridge::Stub> stub_ { nullptr }; ///< The gRPC stub (a.k.a. client).
|
||||
mutable QMutex eventStreamMutex_; ///< The event stream mutex.
|
||||
std::unique_ptr<grpc::ClientContext> eventStreamContext_; /// the client context for the gRPC event stream. Access protected by eventStreamMutex_.
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif // BRIDGE_PP_RPC_CLIENT_H
|
||||
@ -1,175 +0,0 @@
|
||||
// Copyright (c) 2022 Proton AG
|
||||
//
|
||||
// This file is part of Proton Mail Bridge.
|
||||
//
|
||||
// Proton Mail Bridge is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Proton Mail Bridge is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
#include "GRPCUtils.h"
|
||||
#include "../Exception/Exception.h"
|
||||
#include "../BridgeUtils.h"
|
||||
|
||||
|
||||
namespace bridgepp
|
||||
{
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return The server certificate file name
|
||||
//****************************************************************************************************************************************************
|
||||
QString serverCertificateFilename()
|
||||
{
|
||||
return "cert.pem";
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
//
|
||||
//****************************************************************************************************************************************************
|
||||
QString serverKeyFilename()
|
||||
{
|
||||
return "key.pem";
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return The absolute path of the server certificate.
|
||||
//****************************************************************************************************************************************************
|
||||
QString serverCertificatePath()
|
||||
{
|
||||
return QDir(userConfigDir()).absoluteFilePath(serverCertificateFilename());
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return The absolute path of the server key.
|
||||
//****************************************************************************************************************************************************
|
||||
QString serverKeyPath()
|
||||
{
|
||||
return QDir(userConfigDir()).absoluteFilePath(serverKeyFilename());
|
||||
}
|
||||
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] level The Log::Level.
|
||||
/// \return The grpc::LogLevel.
|
||||
//****************************************************************************************************************************************************
|
||||
grpc::LogLevel logLevelToGRPC(Log::Level level)
|
||||
{
|
||||
switch (level)
|
||||
{
|
||||
case Log::Level::Panic:
|
||||
return grpc::LogLevel::LOG_PANIC;
|
||||
case Log::Level::Fatal:
|
||||
return grpc::LogLevel::LOG_FATAL;
|
||||
case Log::Level::Error:
|
||||
return grpc::LogLevel::LOG_ERROR;
|
||||
case Log::Level::Warn:
|
||||
return grpc::LogLevel::LOG_WARN;
|
||||
case Log::Level::Info:
|
||||
return grpc::LogLevel::LOG_INFO;
|
||||
case Log::Level::Debug:
|
||||
return grpc::LogLevel::LOG_DEBUG;
|
||||
case Log::Level::Trace:
|
||||
return grpc::LogLevel::LOG_TRACE;
|
||||
default:
|
||||
throw Exception(QString("unknown log level %1.").arg(qint32(level)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] level The level::LogLevel.
|
||||
/// \return The Log::Level.
|
||||
//****************************************************************************************************************************************************
|
||||
Log::Level logLevelFromGRPC(grpc::LogLevel level)
|
||||
{
|
||||
switch (level)
|
||||
{
|
||||
case grpc::LOG_PANIC:
|
||||
return Log::Level::Panic;
|
||||
case grpc::LOG_FATAL:
|
||||
return Log::Level::Fatal;
|
||||
case grpc::LOG_ERROR:
|
||||
return Log::Level::Error;
|
||||
case grpc::LOG_WARN:
|
||||
return Log::Level::Warn;
|
||||
case grpc::LOG_INFO:
|
||||
return Log::Level::Info;
|
||||
case grpc::LOG_DEBUG:
|
||||
return Log::Level::Debug;
|
||||
case grpc::LOG_TRACE:
|
||||
return Log::Level::Trace;
|
||||
default:
|
||||
throw Exception(QString("unknown log level %1.").arg(qint32(level)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] grpcUser The gRPC user.
|
||||
/// \return user The user.
|
||||
//****************************************************************************************************************************************************
|
||||
SPUser userFromGRPC(grpc::User const &grpcUser)
|
||||
{
|
||||
SPUser user = User::newUser(nullptr);
|
||||
|
||||
user->setID(QString::fromStdString(grpcUser.id()));
|
||||
user->setUsername(QString::fromStdString(grpcUser.username()));
|
||||
user->setPassword(QString::fromStdString(grpcUser.password()));
|
||||
QStringList addresses;
|
||||
for (int j = 0; j < grpcUser.addresses_size(); ++j)
|
||||
addresses.append(QString::fromStdString(grpcUser.addresses(j)));
|
||||
user->setAddresses(addresses);
|
||||
user->setAvatarText(QString::fromStdString(grpcUser.avatartext()));
|
||||
user->setLoggedIn(grpcUser.loggedin());
|
||||
user->setSplitMode(grpcUser.splitmode());
|
||||
user->setSetupGuideSeen(grpcUser.setupguideseen());
|
||||
user->setUsedBytes(float(grpcUser.usedbytes()));
|
||||
user->setTotalBytes(float(grpcUser.totalbytes()));
|
||||
|
||||
return user;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] user the user.
|
||||
/// \param[out] outGRPCUser The GRPC user.
|
||||
//****************************************************************************************************************************************************
|
||||
void userToGRPC(User const &user, grpc::User &outGRPCUser)
|
||||
{
|
||||
outGRPCUser.set_id(user.id().toStdString());
|
||||
outGRPCUser.set_username(user.username().toStdString());
|
||||
outGRPCUser.set_password(user.password().toStdString());
|
||||
outGRPCUser.clear_addresses();
|
||||
for (QString const& address: user.addresses())
|
||||
outGRPCUser.add_addresses(address.toStdString());
|
||||
outGRPCUser.set_avatartext(user.avatarText().toStdString());
|
||||
outGRPCUser.set_loggedin(user.loggedIn());
|
||||
outGRPCUser.set_splitmode(user.splitMode());
|
||||
outGRPCUser.set_setupguideseen(user.setupGuideSeen());
|
||||
outGRPCUser.set_usedbytes(qint64(user.usedBytes()));
|
||||
outGRPCUser.set_totalbytes(qint64(user.totalBytes()));
|
||||
}
|
||||
|
||||
|
||||
} // namespace bridgepp
|
||||
@ -1,45 +0,0 @@
|
||||
// Copyright (c) 2022 Proton AG
|
||||
//
|
||||
// This file is part of Proton Mail Bridge.
|
||||
//
|
||||
// Proton Mail Bridge is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Proton Mail Bridge is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
#ifndef BRIDGE_PP_GRPC_UTILS_H
|
||||
#define BRIDGE_PP_GRPC_UTILS_H
|
||||
|
||||
|
||||
#include "../User/User.h"
|
||||
#include "../Log/Log.h"
|
||||
#include "bridge.grpc.pb.h"
|
||||
|
||||
|
||||
namespace bridgepp
|
||||
{
|
||||
|
||||
|
||||
typedef std::shared_ptr<grpc::StreamEvent> SPStreamEvent; ///< Type definition for shared pointer to grpc::StreamEvent.
|
||||
|
||||
|
||||
QString serverCertificatePath(); ///< Return the path of the server certificate.
|
||||
QString serverKeyPath(); ///< Return the path of the server key.
|
||||
grpc::LogLevel logLevelToGRPC(Log::Level level); ///< Convert a Log::Level to gRPC enum value.
|
||||
Log::Level logLevelFromGRPC(grpc::LogLevel level); ///< Convert a grpc::LogLevel to a Log::Level.
|
||||
void userToGRPC(User const &user, grpc::User &outGRPCUser); ///< Convert a bridgepp::User to a grpc::User.
|
||||
SPUser userFromGRPC(grpc::User const &grpcUser); ///< Create a bridgepp::User from a grpc::User.
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif // BRIDGE_PP_GRPC_UTILS_H
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,272 +0,0 @@
|
||||
// Copyright (c) 2022 Proton AG
|
||||
//
|
||||
// This file is part of Proton Mail Bridge.
|
||||
//
|
||||
// Proton Mail Bridge is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Proton Mail Bridge is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
#include "Log.h"
|
||||
|
||||
|
||||
namespace bridgepp
|
||||
{
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
Log *qtHandlerLog { nullptr }; ///< The log instance handling qt logs.
|
||||
QMutex qtHandlerMutex; ///< A mutex used to access qtHandlerLog.
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] log The log handling qt log entries. Can be null.
|
||||
//****************************************************************************************************************************************************
|
||||
void setQtMessageHandlerLog(Log *log)
|
||||
{
|
||||
QMutexLocker locker(&qtHandlerMutex);
|
||||
qtHandlerLog = log;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return The log handling qt log entries. Can be null.
|
||||
//****************************************************************************************************************************************************
|
||||
Log *qtMessageHandlerLog()
|
||||
{
|
||||
QMutexLocker locker(&qtHandlerMutex);
|
||||
return qtHandlerLog;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] type The message type.
|
||||
/// \param[in] message The message.
|
||||
//****************************************************************************************************************************************************
|
||||
void qtMessageHandler(QtMsgType type, QMessageLogContext const &, QString const &message)
|
||||
{
|
||||
Log *log = qtMessageHandlerLog();
|
||||
if (!log)
|
||||
return;
|
||||
switch (type)
|
||||
{
|
||||
case QtDebugMsg:
|
||||
log->debug(message);
|
||||
break;
|
||||
|
||||
case QtWarningMsg:
|
||||
log->warn(message);
|
||||
break;
|
||||
|
||||
case QtCriticalMsg:
|
||||
case QtFatalMsg:
|
||||
log->error(message);
|
||||
break;
|
||||
|
||||
case QtInfoMsg:
|
||||
default:
|
||||
log->info(message);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] level The level.
|
||||
/// \return A string describing the level.
|
||||
//****************************************************************************************************************************************************
|
||||
QString logLevelToString(Log::Level level)
|
||||
{
|
||||
switch (level)
|
||||
{
|
||||
case Log::Level::Panic:
|
||||
return "PANIC";
|
||||
case Log::Level::Fatal:
|
||||
return "FATAL";
|
||||
case Log::Level::Error:
|
||||
return "ERROR";
|
||||
case Log::Level::Warn:
|
||||
return "WARN";
|
||||
case Log::Level::Info:
|
||||
return "INFO";
|
||||
case Log::Level::Debug:
|
||||
return "DEBUG";
|
||||
case Log::Level::Trace:
|
||||
return "TRACE";
|
||||
default:
|
||||
return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \brief return a string representing the log entry
|
||||
///
|
||||
/// \param[in] level The log entry level.
|
||||
/// \param[in] message The log entry message.
|
||||
/// \return The string for the log entry
|
||||
//****************************************************************************************************************************************************
|
||||
QString Log::logEntryToString(Log::Level level, QString const &message)
|
||||
{
|
||||
return QString("[%1] %2").arg(logLevelToString(level), message);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// the message handle process the message from the Qt logging system.
|
||||
//****************************************************************************************************************************************************
|
||||
void Log::registerAsQtMessageHandler()
|
||||
{
|
||||
setQtMessageHandlerLog(this);
|
||||
qInstallMessageHandler(qtMessageHandler);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
//
|
||||
//****************************************************************************************************************************************************
|
||||
Log::Log()
|
||||
: QObject()
|
||||
, stdout_(stdout)
|
||||
, stderr_(stderr)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] level The log level.
|
||||
//****************************************************************************************************************************************************
|
||||
void Log::setLevel(Log::Level level)
|
||||
{
|
||||
QMutexLocker locker(&mutex_);
|
||||
level_ = level;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return The log level.
|
||||
//****************************************************************************************************************************************************
|
||||
Log::Level Log::level() const
|
||||
{
|
||||
QMutexLocker locker(&mutex_);
|
||||
return Log::Level::Debug;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] value Should the log entries be sent to STDOUT/STDERR.
|
||||
//****************************************************************************************************************************************************
|
||||
void Log::setEchoInConsole(bool value)
|
||||
{
|
||||
QMutexLocker locker(&mutex_);
|
||||
echoInConsole_ = value;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return true iff the log entries be should sent to STDOUT/STDERR.
|
||||
//****************************************************************************************************************************************************
|
||||
bool Log::echoInConsole() const
|
||||
{
|
||||
QMutexLocker locker(&mutex_);
|
||||
return echoInConsole_;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] message The message.
|
||||
//****************************************************************************************************************************************************
|
||||
void Log::panic(QString const &message)
|
||||
{
|
||||
return this->addEntry(Level::Panic, message);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] message The message.
|
||||
//****************************************************************************************************************************************************
|
||||
void Log::fatal(QString const &message)
|
||||
{
|
||||
return this->addEntry(Level::Fatal, message);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] message The message.
|
||||
//****************************************************************************************************************************************************
|
||||
void Log::error(QString const &message)
|
||||
{
|
||||
return this->addEntry(Level::Error, message);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] message The message.
|
||||
//****************************************************************************************************************************************************
|
||||
void Log::warn(QString const &message)
|
||||
{
|
||||
return this->addEntry(Level::Warn, message);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] message The message.
|
||||
//****************************************************************************************************************************************************
|
||||
void Log::info(QString const &message)
|
||||
{
|
||||
return this->addEntry(Level::Info, message);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] message The message.
|
||||
//****************************************************************************************************************************************************
|
||||
void Log::debug(QString const &message)
|
||||
{
|
||||
return this->addEntry(Level::Debug, message);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] message The message.
|
||||
//****************************************************************************************************************************************************
|
||||
void Log::trace(QString const &message)
|
||||
{
|
||||
return this->addEntry(Level::Trace, message);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] level The level.
|
||||
/// \param[in] message The message.
|
||||
//****************************************************************************************************************************************************
|
||||
void Log::addEntry(Log::Level level, QString const &message)
|
||||
{
|
||||
QMutexLocker locker(&mutex_);
|
||||
if (qint32(level) > qint32(level_))
|
||||
return;
|
||||
emit entryAdded(level, message);
|
||||
|
||||
if (echoInConsole_)
|
||||
{
|
||||
QTextStream &stream = (qint32(level) <= (qint32(Level::Warn))) ? stderr_ : stdout_;
|
||||
stream << logEntryToString(level, message) << "\n";
|
||||
stream.flush();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // namespace bridgepp
|
||||
@ -1,91 +0,0 @@
|
||||
// Copyright (c) 2022 Proton AG
|
||||
//
|
||||
// This file is part of Proton Mail Bridge.
|
||||
//
|
||||
// Proton Mail Bridge is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Proton Mail Bridge is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
#ifndef BRIDGE_PP_LOG_H
|
||||
#define BRIDGE_PP_LOG_H
|
||||
|
||||
|
||||
namespace bridgepp
|
||||
{
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \brief Basic log class. No logging to file. Four levels. Rebroadcast received log entries via Qt signals.
|
||||
//****************************************************************************************************************************************************
|
||||
class Log : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public: // data types.
|
||||
/// \brief Log level class. The list matches [loggers log levels](https://pkg.go.dev/github.com/sirupsen/logrus).
|
||||
enum class Level
|
||||
{
|
||||
Panic, ///< Panic log level.
|
||||
Fatal, ///< Fatal log level.
|
||||
Error, ///< Error log level.
|
||||
Warn, ///< Warn log level.
|
||||
Info, ///< Info log level.
|
||||
Debug, ///< Debug log level.
|
||||
Trace ///< Trace log level.
|
||||
};
|
||||
|
||||
public: // static member functions.
|
||||
static QString logEntryToString(Log::Level level, QString const &message); ///< Return a string describing a log entry.
|
||||
|
||||
|
||||
public: // member functions.
|
||||
Log(); ///< Default constructor.
|
||||
Log(Log const &) = delete; ///< Disabled copy-constructor.
|
||||
Log(Log &&) = delete; ///< Disabled assignment copy-constructor.
|
||||
~Log() override = default; ///< Destructor.
|
||||
Log &operator=(Log const &) = delete; ///< Disabled assignment operator.
|
||||
Log &operator=(Log &&) = delete; ///< Disabled move assignment operator.
|
||||
|
||||
void setLevel(Level level); ///< Set the log level.
|
||||
Level level() const; ///< Get the log level.
|
||||
void setEchoInConsole(bool value); ///< Set if the log entries should be echoed in STDOUT/STDERR.
|
||||
bool echoInConsole() const; ///< Check if the log entries should be echoed in STDOUT/STDERR.
|
||||
void registerAsQtMessageHandler(); ///< Install the Qt message handler.
|
||||
|
||||
public slots:
|
||||
void panic(QString const &message); ///< Adds an panic entry to the log.
|
||||
void fatal(QString const &message); ///< Adds an fatal entry to the log.
|
||||
void error(QString const &message); ///< Adds an error entry to the log.
|
||||
void warn(QString const &message); ///< Adds a warn entry to the log.
|
||||
void info(QString const &message); ///< Adds an info entry to the log.
|
||||
void debug(QString const &message); ///< Adds a debug entry in the log.
|
||||
void trace(QString const &message); ///< Adds a trace entry in the log.
|
||||
|
||||
void addEntry(Log::Level level, QString const &message); ///< Adds a trace entry in the log.
|
||||
|
||||
signals:
|
||||
void entryAdded(Log::Level entry, QString const &); ///< Signal emitted when a log entry is added.
|
||||
|
||||
private: // data members
|
||||
mutable QMutex mutex_; ///< The mutex.
|
||||
Level level_{Level::Debug}; ///< The log level
|
||||
bool echoInConsole_{false}; ///< Set if the log messages should be sent to STDOUT/STDERR.
|
||||
|
||||
QTextStream stdout_; ///< The stdout stream.
|
||||
QTextStream stderr_; ///< The stderr stream.
|
||||
};
|
||||
|
||||
|
||||
} // namespace bridgepp
|
||||
|
||||
|
||||
#endif //BRIDGE_PP_LOG_H
|
||||
@ -1,90 +0,0 @@
|
||||
// Copyright (c) 2022 Proton AG
|
||||
//
|
||||
// This file is part of Proton Mail Bridge.
|
||||
//
|
||||
// Proton Mail Bridge is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Proton Mail Bridge is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
#include "ProcessMonitor.h"
|
||||
#include "Exception/Exception.h"
|
||||
|
||||
|
||||
namespace bridgepp
|
||||
{
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] exePath The path of the executable.
|
||||
/// \param[in] args The list of command-line arguments.
|
||||
/// \param[in] parent The parent object of the worker.
|
||||
//****************************************************************************************************************************************************
|
||||
ProcessMonitor::ProcessMonitor(QString const &exePath, QStringList const &args, QObject *parent)
|
||||
: Worker(parent)
|
||||
, exePath_(exePath)
|
||||
, args_(args)
|
||||
{
|
||||
QFileInfo fileInfo(exePath);
|
||||
if (!fileInfo.exists())
|
||||
throw Exception(QString("Could not locate %1 executable.").arg(fileInfo.baseName()));
|
||||
if ((!fileInfo.isFile()) || (!fileInfo.isExecutable()))
|
||||
throw Exception(QString("Invalid %1 executable").arg(fileInfo.baseName()));
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
//
|
||||
//****************************************************************************************************************************************************
|
||||
void ProcessMonitor::run()
|
||||
{
|
||||
try
|
||||
{
|
||||
emit started();
|
||||
|
||||
QProcess p;
|
||||
p.start(exePath_, args_);
|
||||
p.waitForStarted();
|
||||
|
||||
status_.running = true;
|
||||
status_.pid = p.processId();
|
||||
|
||||
while (!p.waitForFinished(100))
|
||||
{
|
||||
// we discard output from bridge, it's logged to file on bridge side.
|
||||
p.readAllStandardError();
|
||||
p.readAllStandardOutput();
|
||||
}
|
||||
|
||||
status_.running = false;
|
||||
status_.returnCode = p.exitCode();
|
||||
|
||||
emit processExited(status_.returnCode);
|
||||
emit finished();
|
||||
}
|
||||
catch (Exception const &e)
|
||||
{
|
||||
emit error(e.qwhat());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return status of the monitored process
|
||||
//****************************************************************************************************************************************************
|
||||
const ProcessMonitor::MonitorStatus &ProcessMonitor::getStatus()
|
||||
{
|
||||
return status_;
|
||||
}
|
||||
|
||||
|
||||
} // namespace bridgepp
|
||||
@ -1,67 +0,0 @@
|
||||
// Copyright (c) 2022 Proton AG
|
||||
//
|
||||
// This file is part of Proton Mail Bridge.
|
||||
//
|
||||
// Proton Mail Bridge is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Proton Mail Bridge is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
#ifndef BRIDGE_PP_PROCESS_MONITOR_H
|
||||
#define BRIDGE_PP_PROCESS_MONITOR_H
|
||||
|
||||
|
||||
#include "Worker/Worker.h"
|
||||
|
||||
|
||||
namespace bridgepp
|
||||
{
|
||||
|
||||
|
||||
//**********************************************************************************************************************
|
||||
/// \brief Process launcher and monitor class.
|
||||
//**********************************************************************************************************************
|
||||
class ProcessMonitor : public Worker
|
||||
{
|
||||
Q_OBJECT
|
||||
public: // static member functions
|
||||
struct MonitorStatus
|
||||
{
|
||||
bool running = false;
|
||||
int returnCode = 0;
|
||||
qint64 pid = 0;
|
||||
};
|
||||
|
||||
public: // member functions.
|
||||
ProcessMonitor(QString const &exePath, QStringList const &args, QObject *parent); ///< Default constructor.
|
||||
ProcessMonitor(ProcessMonitor const &) = delete; ///< Disabled copy-constructor.
|
||||
ProcessMonitor(ProcessMonitor &&) = delete; ///< Disabled assignment copy-constructor.
|
||||
~ProcessMonitor() override = default; ///< Destructor.
|
||||
ProcessMonitor &operator=(ProcessMonitor const &) = delete; ///< Disabled assignment operator.
|
||||
ProcessMonitor &operator=(ProcessMonitor &&) = delete; ///< Disabled move assignment operator.
|
||||
void run() override; ///< Run the worker.
|
||||
MonitorStatus const &getStatus();
|
||||
|
||||
signals:
|
||||
void processExited(int code); ///< Slot for the exiting of the process.
|
||||
|
||||
private: // data members
|
||||
QString const exePath_; ///< The path to the executable.
|
||||
QStringList args_; ///< arguments to be passed to the brigde.
|
||||
MonitorStatus status_; ///< Status of the monitoring.
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif //BRIDGE_PP_PROCESS_MONITOR_H
|
||||
@ -1,329 +0,0 @@
|
||||
// Copyright (c) 2022 Proton AG
|
||||
//
|
||||
// This file is part of Proton Mail Bridge.
|
||||
//
|
||||
// Proton Mail Bridge is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Proton Mail Bridge is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
#include "User.h"
|
||||
|
||||
|
||||
namespace bridgepp
|
||||
{
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] parent The parent object of the user.
|
||||
//****************************************************************************************************************************************************
|
||||
SPUser User::newUser(QObject *parent)
|
||||
{
|
||||
return SPUser(new User(parent));
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] parent The parent object.
|
||||
//****************************************************************************************************************************************************
|
||||
User::User(QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] user The user to copy from
|
||||
//****************************************************************************************************************************************************
|
||||
void User::update(User const &user)
|
||||
{
|
||||
this->setID(user.id());
|
||||
this->setUsername(user.username());
|
||||
this->setPassword(user.password());
|
||||
this->setAddresses(user.addresses());
|
||||
this->setAvatarText(user.avatarText());
|
||||
this->setLoggedIn(user.loggedIn());
|
||||
this->setSplitMode(user.splitMode());
|
||||
this->setSetupGuideSeen(user.setupGuideSeen());
|
||||
this->setUsedBytes(user.usedBytes());
|
||||
this->setTotalBytes(user.totalBytes());
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] makeItActive Should split mode be made active.
|
||||
//****************************************************************************************************************************************************
|
||||
void User::toggleSplitMode(bool makeItActive)
|
||||
{
|
||||
emit toggleSplitModeForUser(id_, makeItActive);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
//
|
||||
//****************************************************************************************************************************************************
|
||||
void User::logout()
|
||||
{
|
||||
emit logoutUser(id_);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
//
|
||||
//****************************************************************************************************************************************************
|
||||
void User::remove()
|
||||
{
|
||||
emit removeUser(id_);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] address The email address to configure Apple Mail for.
|
||||
//****************************************************************************************************************************************************
|
||||
void User::configureAppleMail(QString const &address)
|
||||
{
|
||||
emit configureAppleMailForUser(id_, address);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
// The only purpose of this call is to forward to the QML application the toggleSplitModeFinished(userID) event
|
||||
// that was received by the UserList model.
|
||||
//****************************************************************************************************************************************************
|
||||
void User::emitToggleSplitModeFinished()
|
||||
{
|
||||
emit toggleSplitModeFinished();
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return The userID.
|
||||
//****************************************************************************************************************************************************
|
||||
QString User::id() const
|
||||
{
|
||||
return id_;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] id The userID.
|
||||
//****************************************************************************************************************************************************
|
||||
void User::setID(QString const &id)
|
||||
{
|
||||
if (id == id_)
|
||||
return;
|
||||
|
||||
id_ = id;
|
||||
emit idChanged(id_);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return The username.
|
||||
//****************************************************************************************************************************************************
|
||||
QString User::username() const
|
||||
{
|
||||
return username_;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] username The username.
|
||||
//****************************************************************************************************************************************************
|
||||
void User::setUsername(QString const &username)
|
||||
{
|
||||
if (username == username_)
|
||||
return;
|
||||
|
||||
username_ = username;
|
||||
emit usernameChanged(username_);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return The password.
|
||||
//****************************************************************************************************************************************************
|
||||
QString User::password() const
|
||||
{
|
||||
return password_;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] password The password.
|
||||
//****************************************************************************************************************************************************
|
||||
void User::setPassword(QString const &password)
|
||||
{
|
||||
if (password == password_)
|
||||
return;
|
||||
|
||||
password_ = password;
|
||||
emit passwordChanged(password_);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return The addresses.
|
||||
//****************************************************************************************************************************************************
|
||||
QStringList User::addresses() const
|
||||
{
|
||||
return addresses_;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] addresses The addresses.
|
||||
//****************************************************************************************************************************************************
|
||||
void User::setAddresses(QStringList const &addresses)
|
||||
{
|
||||
if (addresses == addresses_)
|
||||
return;
|
||||
|
||||
addresses_ = addresses;
|
||||
emit addressesChanged(addresses_);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return The avatar text.
|
||||
//****************************************************************************************************************************************************
|
||||
QString User::avatarText() const
|
||||
{
|
||||
return avatarText_;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] avatarText The avatar text.
|
||||
//****************************************************************************************************************************************************
|
||||
void User::setAvatarText(QString const &avatarText)
|
||||
{
|
||||
if (avatarText == avatarText_)
|
||||
return;
|
||||
|
||||
avatarText_ = avatarText;
|
||||
emit usernameChanged(avatarText_);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return The login status.
|
||||
//****************************************************************************************************************************************************
|
||||
bool User::loggedIn() const
|
||||
{
|
||||
return loggedIn_;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] loggedIn The login status.
|
||||
//****************************************************************************************************************************************************
|
||||
void User::setLoggedIn(bool loggedIn)
|
||||
{
|
||||
if (loggedIn == loggedIn_)
|
||||
return;
|
||||
|
||||
loggedIn_ = loggedIn;
|
||||
emit loggedInChanged(loggedIn_);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return The split mode status.
|
||||
//****************************************************************************************************************************************************
|
||||
bool User::splitMode() const
|
||||
{
|
||||
return splitMode_;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] splitMode The split mode status.
|
||||
//****************************************************************************************************************************************************
|
||||
void User::setSplitMode(bool splitMode)
|
||||
{
|
||||
if (splitMode == splitMode_)
|
||||
return;
|
||||
|
||||
splitMode_ = splitMode;
|
||||
emit splitModeChanged(splitMode_);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return The 'Setup Guide Seen' status.
|
||||
//****************************************************************************************************************************************************
|
||||
bool User::setupGuideSeen() const
|
||||
{
|
||||
return setupGuideSeen_;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] setupGuideSeen The 'Setup Guide Seen' status.
|
||||
//****************************************************************************************************************************************************
|
||||
void User::setSetupGuideSeen(bool setupGuideSeen)
|
||||
{
|
||||
if (setupGuideSeen == setupGuideSeen_)
|
||||
return;
|
||||
|
||||
setupGuideSeen_ = setupGuideSeen;
|
||||
emit setupGuideSeenChanged(setupGuideSeen_);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return The used bytes.
|
||||
//****************************************************************************************************************************************************
|
||||
float User::usedBytes() const
|
||||
{
|
||||
return usedBytes_;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] usedBytes The used bytes.
|
||||
//****************************************************************************************************************************************************
|
||||
void User::setUsedBytes(float usedBytes)
|
||||
{
|
||||
if (usedBytes == usedBytes_)
|
||||
return;
|
||||
|
||||
usedBytes_ = usedBytes;
|
||||
emit usedBytesChanged(usedBytes_);
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return The total bytes.
|
||||
//****************************************************************************************************************************************************
|
||||
float User::totalBytes() const
|
||||
{
|
||||
return totalBytes_;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] totalBytes The total bytes.
|
||||
//****************************************************************************************************************************************************
|
||||
void User::setTotalBytes(float totalBytes)
|
||||
{
|
||||
if (totalBytes == totalBytes_)
|
||||
return;
|
||||
|
||||
totalBytes_ = totalBytes;
|
||||
emit totalBytesChanged(totalBytes_);
|
||||
}
|
||||
|
||||
|
||||
} // namespace bridgepp
|
||||
@ -1,130 +0,0 @@
|
||||
// Copyright (c) 2022 Proton AG
|
||||
//
|
||||
// This file is part of Proton Mail Bridge.
|
||||
//
|
||||
// Proton Mail Bridge is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Proton Mail Bridge is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
#ifndef BRIDGE_PP_USER_H
|
||||
#define BRIDGE_PP_USER_H
|
||||
|
||||
|
||||
namespace bridgepp
|
||||
{
|
||||
|
||||
|
||||
typedef std::shared_ptr<class User> SPUser; ///< Type definition for shared pointer to user.
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \brief User class.
|
||||
//****************************************************************************************************************************************************
|
||||
class User : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public: // static member function
|
||||
static SPUser newUser(QObject *parent); ///< Create a new user
|
||||
|
||||
public: // member functions.
|
||||
User(User const &) = delete; ///< Disabled copy-constructor.
|
||||
User(User &&) = delete; ///< Disabled assignment copy-constructor.
|
||||
~User() override = default; ///< Destructor.
|
||||
User &operator=(User const &) = delete; ///< Disabled assignment operator.
|
||||
User &operator=(User &&) = delete; ///< Disabled move assignment operator.
|
||||
void update(User const &user); ///< Update the user.
|
||||
|
||||
public slots:
|
||||
// slots for QML generated calls
|
||||
void toggleSplitMode(bool makeItActive); // _ func(makeItActive bool) `slot:"toggleSplitMode"`
|
||||
void logout(); // _ func() `slot:"logout"`
|
||||
void remove(); // _ func() `slot:"remove"`
|
||||
void configureAppleMail(QString const &address); // _ func(address string) `slot:"configureAppleMail"`
|
||||
void emitToggleSplitModeFinished(); // slot for external signals
|
||||
|
||||
signals: // signal used to forward QML event received in the above slots
|
||||
void toggleSplitModeForUser(QString const &userID, bool makeItActive);
|
||||
void logoutUser(QString const &userID);
|
||||
void removeUser(QString const &userID);
|
||||
void configureAppleMailForUser(QString const &userID, QString const &address);
|
||||
|
||||
|
||||
public:
|
||||
Q_PROPERTY(QString id READ id WRITE setID NOTIFY idChanged) // _ string ID
|
||||
Q_PROPERTY(QString username READ username WRITE setUsername NOTIFY usernameChanged) // _ string `property:"username"`
|
||||
Q_PROPERTY(QString password READ password WRITE setPassword NOTIFY passwordChanged) // _ string `property:"password"`
|
||||
Q_PROPERTY(QStringList addresses READ addresses WRITE setAddresses NOTIFY addressesChanged) // _ []string `property:"addresses"`
|
||||
Q_PROPERTY(QString avatarText READ avatarText WRITE setAvatarText NOTIFY avatarTextChanged) // _ string `property:"avatarText"`
|
||||
Q_PROPERTY(bool loggedIn READ loggedIn WRITE setLoggedIn NOTIFY loggedInChanged) // _ bool `property:"loggedIn"`
|
||||
Q_PROPERTY(bool splitMode READ splitMode WRITE setSplitMode NOTIFY splitModeChanged) // _ bool `property:"splitMode"`
|
||||
Q_PROPERTY(bool setupGuideSeen READ setupGuideSeen WRITE setSetupGuideSeen NOTIFY setupGuideSeenChanged) // _ bool `property:"setupGuideSeen"`
|
||||
Q_PROPERTY(float usedBytes READ usedBytes WRITE setUsedBytes NOTIFY usedBytesChanged) // _ float32 `property:"usedBytes"`
|
||||
Q_PROPERTY(float totalBytes READ totalBytes WRITE setTotalBytes NOTIFY totalBytesChanged) // _ float32 `property:"totalBytes"`
|
||||
|
||||
QString id() const;
|
||||
void setID(QString const &id);
|
||||
QString username() const;
|
||||
void setUsername(QString const &username);
|
||||
QString password() const;
|
||||
void setPassword(QString const &password);
|
||||
QStringList addresses() const;
|
||||
void setAddresses(QStringList const &addresses);
|
||||
QString avatarText() const;
|
||||
void setAvatarText(QString const &avatarText);
|
||||
bool loggedIn() const;
|
||||
void setLoggedIn(bool loggedIn);
|
||||
bool splitMode() const;
|
||||
void setSplitMode(bool splitMode);
|
||||
bool setupGuideSeen() const;
|
||||
void setSetupGuideSeen(bool setupGuideSeen);
|
||||
float usedBytes() const;
|
||||
void setUsedBytes(float usedBytes);
|
||||
float totalBytes() const;
|
||||
void setTotalBytes(float totalBytes);
|
||||
|
||||
signals:
|
||||
// signals used for Qt properties
|
||||
void idChanged(QString const &id);
|
||||
void usernameChanged(QString const &username);
|
||||
void passwordChanged(QString const &);
|
||||
void addressesChanged(QStringList const &);
|
||||
void avatarTextChanged(QString const &avatarText);
|
||||
void loggedInChanged(bool loggedIn);
|
||||
void splitModeChanged(bool splitMode);
|
||||
void setupGuideSeenChanged(bool seen);
|
||||
void usedBytesChanged(float byteCount);
|
||||
void totalBytesChanged(float byteCount);
|
||||
|
||||
void toggleSplitModeFinished();
|
||||
|
||||
private: // member functions.
|
||||
User(QObject *parent); ///< Default constructor.
|
||||
|
||||
private: // data members.
|
||||
QString id_; ///< The userID.
|
||||
QString username_; ///< The username
|
||||
QString password_; ///< The IMAP password of the user.
|
||||
QStringList addresses_; ///< The email address list of the user.
|
||||
QString avatarText_; ///< The avatar text (i.e. initials of the user)
|
||||
bool loggedIn_ { true }; ///< Is the user logged in.
|
||||
bool splitMode_ { false }; ///< Is split mode active.
|
||||
bool setupGuideSeen_ { false }; ///< Has the setup guide been seen.
|
||||
float usedBytes_ { 0.0f }; ///< The storage used by the user.
|
||||
float totalBytes_ { 1.0f }; ///< The storage quota of the user.
|
||||
};
|
||||
|
||||
|
||||
} // namespace bridgepp
|
||||
|
||||
|
||||
#endif // BRIDGE_PP_USER_H
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user