Compare commits

...

29 Commits

Author SHA1 Message Date
b5321f8993 Other: Bridge Nihonbashi 2.3.0 (fix 1840) 2022-08-31 17:03:07 +02:00
bcf799732f GODT-1840: Safe map for mailboxID cache 2022-08-31 15:48:40 +02:00
13ba2182c2 Other: Bridge Nihonbashi 2.3.0 2022-08-30 15:34:31 +02:00
0d25c607e7 GODT-1795: fix automatic installation of profile for AppleMail on macOS Ventura beta (qt 5). 2022-08-30 08:37:50 +00:00
b3f8866ef7 GODT-1737: Improve logging during import 2022-08-29 16:10:28 +02:00
9bb16dec48 GODT-1754: Add logs for unilateral updates and SEARCH. 2022-08-29 16:09:54 +02:00
bdb35f1c1d GODT-1799: fix dependency link [skip-ci] 2022-08-29 16:09:17 +02:00
d421b5aa5a GODT-1833: Fix gobinsec cache. 2022-08-29 15:51:20 +02:00
1ec05e8a6c GODT-1794: CLI wording 2022-08-26 16:49:58 +02:00
5b941013de Other: Update SSL certificate fingerprint for test 2022-08-26 16:43:24 +02:00
a93ed35eee GODT-1794: Add confirmation dialog and change wording 2022-08-26 15:01:18 +02:00
76469969f3 GODT-1741: GUI and CLI settings to change visibility of All Mail folder. 2022-08-25 13:43:33 +02:00
8b39ea4acb GODT-1740: Opt-out All Mail visibility in settings file. 2022-08-16 23:43:19 +02:00
252ca9a5f9 Other: Bridge Millau 2.2.2 2022-08-16 16:05:42 +02:00
c4eb1a0f5b GODT-1743: Terminate running bridge if has old version. 2022-08-16 16:05:42 +02:00
1e2f4e9ebb GODT-1743: Quit bridge when opening manual install 2022-08-16 16:05:42 +02:00
2a7aefac45 Other: Introduce gobinsec cache. 2022-08-16 16:05:42 +02:00
ea39e2d842 Other: Bridge Millau 2.2.1 2022-08-16 16:05:42 +02:00
fc5879a204 GODT-1565: Improve mac icon. 2022-08-16 16:05:42 +02:00
5ae2229e37 GODT-1475: Improve systray icon size. 2022-08-16 16:05:42 +02:00
12e5ce0ff0 GODT-1565: Update Bridge application icons. 2022-08-16 16:05:42 +02:00
5ef3774d11 GODT-1564: Update welcome illustration 2022-08-16 16:05:42 +02:00
654e816e6b GODT-1686: Add Label/Folder filtering to pmapi 2022-08-16 16:05:42 +02:00
7cad7bcddb GODT-1659: Convert charset only for text/* MIME types. 2022-08-16 16:05:42 +02:00
136d514cf7 GODT-1626: Update gopenpgp v2.4.7
This patch also replaces the deprecated calls to `SeparateKeyAndData`
with `SplitMessage`.
2022-08-16 16:05:42 +02:00
6e48345d54 GODT-1627: Update go-srvp to v0.0.5 2022-08-16 16:05:42 +02:00
8ebdb466f7 GODT-1523: Reduce unnecessary shell executions. Inspired by @kortschak. 2022-08-16 15:56:10 +02:00
1ed7b690a5 mitigate shelling out behaviour risks 2022-08-16 15:46:44 +02:00
5c28a3eda7 Don't shell out to obtain process and system stats 2022-08-16 15:46:34 +02:00
121 changed files with 2099 additions and 513 deletions

2
.gitignore vendored
View File

@ -5,6 +5,7 @@
# Editor files # Editor files
.*.sw? .*.sw?
*~ *~
.idea
# Test files # Test files
godog.test godog.test
@ -29,3 +30,4 @@ vendor-cache
/hasher /hasher
cmd/Desktop-Bridge/deploy cmd/Desktop-Bridge/deploy
cmd/Import-Export/deploy cmd/Import-Export/deploy
proton-bridge

View File

@ -38,6 +38,7 @@ stages:
- cache - cache
- test - test
- build - build
- check
- mirror - mirror
# Stage: CACHE # Stage: CACHE
@ -107,7 +108,8 @@ test-integration:
dependency-updates: dependency-updates:
stage: test stage: test
script: script:
- make updates - "echo 'NOTE: Do not run on go1.15 ( 'if...' can be removed once fully updated to go1.18)'"
- if [ 18 -le $(go version | cut -d. -f2 | cut -d " " -f1) ]; then make updates; fi
# Stage: BUILD # Stage: BUILD
@ -138,9 +140,6 @@ build-qml:
script: script:
- make build - make build
- git diff && git diff-index --quiet HEAD - git diff && git diff-index --quiet HEAD
- curl -L https://services.nvd.nist.gov/rest/json/cves/1.0/
- gobinsec -verbose -wait -config utils/gobinsec_conf.yml
cmd/Desktop-Bridge/deploy/linux/proton-bridge
artifacts: artifacts:
# Note: The latest artifacts for refs are locked against deletion, and kept # Note: The latest artifacts for refs are locked against deletion, and kept
# regardless of the expiry time. Introduced in GitLab 13.0 behind a # regardless of the expiry time. Introduced in GitLab 13.0 behind a
@ -180,6 +179,7 @@ build-linux-qa:
- export PATH=$GOPATH/bin:$PATH - export PATH=$GOPATH/bin:$PATH
- export CGO_CPPFLAGS='-Wno-error -Wno-nullability-completeness -Wno-expansion-to-defined -Wno-builtin-requires-header' - export CGO_CPPFLAGS='-Wno-error -Wno-nullability-completeness -Wno-expansion-to-defined -Wno-builtin-requires-header'
script: script:
- go version
- make build - make build
- git diff && git diff-index --quiet HEAD - git diff && git diff-index --quiet HEAD
cache: {} cache: {}
@ -234,6 +234,27 @@ build-windows-qa:
artifacts: artifacts:
name: "bridge-windows-qa-$CI_COMMIT_SHORT_SHA" name: "bridge-windows-qa-$CI_COMMIT_SHORT_SHA"
# Stage: CHECK
check-gobinsec:
stage: check
only:
- branches
cache:
key: gobinsec-cache
paths:
- gobinsec-cache.yml
policy: pull-push
before_script:
- mkdir build
- tar -xzf bridge_linux_*.tgz -C build
- "echo api-key: \"${GOBINSEC_NVD_API_KEY}\" >> utils/gobinsec_conf.yml"
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
# Stage: MIRROR # Stage: MIRROR
mirror-repo: mirror-repo:

View File

@ -23,9 +23,9 @@ Proton Mail Bridge includes the following 3rd party software:
<!-- START AUTOGEN --> <!-- 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) * [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) * [go-imap](https://github.com/emersion/go-imap) available under [license](https://github.com/emersion/go-imap/blob/master/LICENSE)
* [bcrypt](https://github.com/jameskeane/bcrypt) available under [license](https://github.com/jameskeane/bcrypt/blob/master/LICENSE)
* [notificator](https://github.com/0xAX/notificator) available under [license](https://github.com/0xAX/notificator/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) * [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-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-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) * [go-imap-id](https://github.com/ProtonMail/go-imap-id) available under [license](https://github.com/ProtonMail/go-imap-id/blob/master/LICENSE)
@ -61,6 +61,7 @@ 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) * [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) * [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) * [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) * [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) * [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) * [text](https://github.com/kr/text) available under [license](https://github.com/kr/text/blob/master/LICENSE)
@ -88,6 +89,5 @@ Proton Mail Bridge includes the following 3rd party software:
* [docker-credential-helpers](https://github.com/ProtonMail/docker-credential-helpers) available under [license](https://github.com/ProtonMail/docker-credential-helpers/blob/master/LICENSE) * [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-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) * [go-message](https://github.com/ProtonMail/go-message) available under [license](https://github.com/ProtonMail/go-message/blob/master/LICENSE)
* [bcrypt](https://github.com/ProtonMail/bcrypt) available under [license](https://github.com/ProtonMail/bcrypt/blob/master/LICENSE)
* [go-keychain](https://github.com/cuthix/go-keychain) available under [license](https://github.com/cuthix/go-keychain/blob/master/LICENSE) * [go-keychain](https://github.com/cuthix/go-keychain) available under [license](https://github.com/cuthix/go-keychain/blob/master/LICENSE)
<!-- END AUTOGEN --> <!-- END AUTOGEN -->

View File

@ -2,6 +2,59 @@
Changelog [format](http://keepachangelog.com/en/1.0.0/) Changelog [format](http://keepachangelog.com/en/1.0.0/)
## [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
* Introduced gobinsec cache.
### Fixed
* GODT-1743: Terminate running bridge if has old version.
* GODT-1743: Quit bridge when opening manual install.
## [Bridge 2.2.1] Millau
### Added
* GODT-1550: Add gobinsec check after CI build.
* GODT-1686: Add Label/Folder filtering to pmapi.
### Changed
* Rebranding:
* GODT-1475: Change systray icons.
* GODT-1565: Update Bridge application icons.
* GODT-1564: Update welcome illustration.
* GODT-1626: Update gopenpgp v2.4.7.
* GODT-1627: Update go-srvp to v0.0.5.
* GODT-1523: Reduce unnecessary shell executions. Inspired by @kortschak.
* Other: Add v2 to module name.
* GODT-1562: Update test fingerpring.
### Fixed
* GODT-1659: Convert charset only for `text/*` MIME types.
* GODT-1640: Renew test keys.
## [Bridge 2.2.0] Millau ## [Bridge 2.2.0] Millau
### Added ### Added

View File

@ -10,11 +10,11 @@ TARGET_OS?=${GOOS}
.PHONY: build 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. # Keep version hardcoded so app build works also without Git repository.
BRIDGE_APP_VERSION?=2.2.0+git BRIDGE_APP_VERSION?=2.3.0+git
APP_VERSION:=${BRIDGE_APP_VERSION} APP_VERSION:=${BRIDGE_APP_VERSION}
SRC_ICO:=logo.ico SRC_ICO:=bridge.ico
SRC_ICNS:=Bridge.icns SRC_ICNS:=Bridge.icns
SRC_SVG:=logo.svg SRC_SVG:=bridge.svg
EXE_NAME:=proton-bridge EXE_NAME:=proton-bridge
CONFIGNAME:=bridge CONFIGNAME:=bridge
REVISION:=$(shell git rev-parse --short=10 HEAD) REVISION:=$(shell git rev-parse --short=10 HEAD)
@ -88,7 +88,7 @@ ${TGZ_TARGET}: ${DEPLOY_DIR}/${TARGET_OS}
cd ${DEPLOY_DIR}/${TARGET_OS} && tar -czvf ../../../../$@ . cd ${DEPLOY_DIR}/${TARGET_OS} && tar -czvf ../../../../$@ .
${DEPLOY_DIR}/linux: ${EXE_TARGET} ${DEPLOY_DIR}/linux: ${EXE_TARGET}
cp -pf ./internal/frontend/share/${SRC_SVG} ${DEPLOY_DIR}/linux/logo.svg cp -pf ./dist/${SRC_SVG} ${DEPLOY_DIR}/linux/logo.svg
cp -pf ./LICENSE ${DEPLOY_DIR}/linux/ cp -pf ./LICENSE ${DEPLOY_DIR}/linux/
cp -pf ./Changelog.md ${DEPLOY_DIR}/linux/ cp -pf ./Changelog.md ${DEPLOY_DIR}/linux/
cp -pf ./dist/${EXE_NAME}.desktop ${DEPLOY_DIR}/linux/ cp -pf ./dist/${EXE_NAME}.desktop ${DEPLOY_DIR}/linux/
@ -98,7 +98,7 @@ ${DEPLOY_DIR}/darwin: ${EXE_TARGET}
mv ${EXE_TARGET}/Contents/MacOS/{${DIRNAME},${EXE_NAME}}; \ mv ${EXE_TARGET}/Contents/MacOS/{${DIRNAME},${EXE_NAME}}; \
perl -i -pe"s/>${DIRNAME}/>${EXE_NAME}/g" ${EXE_TARGET}/Contents/Info.plist; \ perl -i -pe"s/>${DIRNAME}/>${EXE_NAME}/g" ${EXE_TARGET}/Contents/Info.plist; \
fi fi
cp ./internal/frontend/share/${SRC_ICNS} ${DARWINAPP_CONTENTS}/Resources/${SRC_ICNS} cp ./dist/${SRC_ICNS} ${DARWINAPP_CONTENTS}/Resources/${SRC_ICNS}
cp LICENSE ${DARWINAPP_CONTENTS}/Resources/ cp LICENSE ${DARWINAPP_CONTENTS}/Resources/
rm -rf "${DARWINAPP_CONTENTS}/Frameworks/QtWebEngine.framework" rm -rf "${DARWINAPP_CONTENTS}/Frameworks/QtWebEngine.framework"
rm -rf "${DARWINAPP_CONTENTS}/Frameworks/QtWebView.framework" rm -rf "${DARWINAPP_CONTENTS}/Frameworks/QtWebView.framework"
@ -106,7 +106,7 @@ ${DEPLOY_DIR}/darwin: ${EXE_TARGET}
./utils/remove_non_relative_links_darwin.sh "${EXE_TARGET}${EXE_BINARY_DARWIN}" ./utils/remove_non_relative_links_darwin.sh "${EXE_TARGET}${EXE_BINARY_DARWIN}"
${DEPLOY_DIR}/windows: ${EXE_TARGET} ${DEPLOY_DIR}/windows: ${EXE_TARGET}
cp ./internal/frontend/share/${SRC_ICO} ${DEPLOY_DIR}/windows/logo.ico cp ./dist/${SRC_ICO} ${DEPLOY_DIR}/windows/logo.ico
cp LICENSE ${DEPLOY_DIR}/windows/ cp LICENSE ${DEPLOY_DIR}/windows/
QT_BUILD_TARGET:=build desktop QT_BUILD_TARGET:=build desktop
@ -127,7 +127,7 @@ ${EXE_TARGET}: check-has-go gofiles ${RESOURCE_FILE} ${VENDOR_TARGET}
WINDRES_YEAR:=$(shell date +%Y) WINDRES_YEAR:=$(shell date +%Y)
APP_VERSION_COMMA:=$(shell echo "${APP_VERSION}" | sed -e 's/[^0-9,.]*//g' -e 's/\./,/g') APP_VERSION_COMMA:=$(shell echo "${APP_VERSION}" | sed -e 's/[^0-9,.]*//g' -e 's/\./,/g')
resource.syso: ./internal/frontend/share/info.rc ./internal/frontend/share/${SRC_ICO} .FORCE resource.syso: ./dist/info.rc ./dist/${SRC_ICO} .FORCE
rm -f ./*.syso 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 $@ $< 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 $@ $<
@ -166,7 +166,7 @@ update-qt-docs:
LINTVER:="v1.39.0" LINTVER:="v1.39.0"
LINTSRC:="https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh" LINTSRC:="https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh"
install-dev-dependencies: install-devel-tools install-linter install-go-mod-outdated install-dev-dependencies: install-devel-tools install-linter
install-devel-tools: check-has-go install-devel-tools: check-has-go
go get -v github.com/golang/mock/gomock go get -v github.com/golang/mock/gomock

View File

@ -20,7 +20,6 @@ package main
import ( import (
"fmt" "fmt"
"os" "os"
"os/exec"
"path/filepath" "path/filepath"
"runtime" "runtime"
@ -36,6 +35,7 @@ import (
"github.com/ProtonMail/proton-bridge/v2/internal/versioner" "github.com/ProtonMail/proton-bridge/v2/internal/versioner"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"golang.org/x/sys/execabs"
) )
const ( const (
@ -98,7 +98,7 @@ func main() { //nolint:funlen
logrus.WithError(err).Fatal("Failed to determine path to launcher") logrus.WithError(err).Fatal("Failed to determine path to launcher")
} }
cmd := exec.Command(exe, appendLauncherPath(launcher, os.Args[1:])...) //nolint:gosec cmd := execabs.Command(exe, appendLauncherPath(launcher, os.Args[1:])...) //nolint:gosec
cmd.Stdin = os.Stdin cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout cmd.Stdout = os.Stdout

BIN
dist/Bridge.icns vendored Normal file

Binary file not shown.

BIN
dist/bridge.ico vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 124 KiB

32
dist/bridge.svg vendored Normal file
View File

@ -0,0 +1,32 @@
<svg width="256" height="256" viewBox="0 0 256 256" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_9588_57903)">
<path d="M127.416 -0.0898438C63.1423 -0.0898438 11.0449 51.9864 11.0449 116.234V233.331C11.0449 245.779 21.1405 255.871 33.5942 255.871H223.647C234.767 255.871 243.788 246.853 243.788 235.738V116.234C243.788 51.9948 191.691 -0.0898438 127.416 -0.0898438ZM194.401 115.589L143.537 158.421C134.357 166.155 120.929 166.155 111.749 158.421L60.8849 115.589C60.8849 79.2409 90.3659 49.7718 126.728 49.7718H128.558C164.92 49.7718 194.401 79.2409 194.401 115.589Z" fill="#6D4AFF"/>
<path d="M127.416 -0.0898438C63.1423 -0.0898438 11.0449 51.9864 11.0449 116.234V233.331C11.0449 245.779 21.1405 255.871 33.5942 255.871H223.647C234.767 255.871 243.788 246.853 243.788 235.738V116.234C243.788 51.9948 191.691 -0.0898438 127.416 -0.0898438ZM194.401 115.589L143.537 158.421C134.357 166.155 120.929 166.155 111.749 158.421L60.8849 115.589C60.8849 79.2409 90.3659 49.7718 126.728 49.7718H128.558C164.92 49.7718 194.401 79.2409 194.401 115.589Z" fill="url(#paint0_linear_9588_57903)"/>
<g filter="url(#filter0_i_9588_57903)">
<path d="M143.572 158.939C138.271 163.23 124.489 169.238 111.766 158.939C99.0439 148.64 72.6401 125.871 61.0285 115.774H61.0868L60.8676 115.59C60.8676 79.2418 90.3367 49.7728 126.684 49.7728H128.513C164.861 49.7728 194.33 79.2418 194.33 115.59L194.111 115.774H194.31V255.872H223.564C234.679 255.872 243.697 246.854 243.697 235.739V116.235C243.697 51.9958 191.62 -0.0888672 127.372 -0.0888672C63.1241 -0.0888672 11.0479 51.9874 11.0479 116.235V123.587L82.9896 185.444C88.2906 190.492 102.224 197.56 115.553 185.444C128.881 173.327 139.786 162.726 143.572 158.939Z" fill="url(#paint1_radial_9588_57903)"/>
</g>
</g>
<defs>
<filter id="filter0_i_9588_57903" x="7.29545" y="-0.0888672" width="236.401" height="266.43" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="-3.7524" dy="10.4692"/>
<feGaussianBlur stdDeviation="28.143"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.462745 0 0 0 0 0.337255 0 0 0 0 1 0 0 0 0.24 0"/>
<feBlend mode="normal" in2="shape" result="effect1_innerShadow_9588_57903"/>
</filter>
<linearGradient id="paint0_linear_9588_57903" x1="19.3784" y1="285.405" x2="54.2022" y2="186.949" gradientUnits="userSpaceOnUse">
<stop stop-color="#28B0E8"/>
<stop offset="1" stop-color="#C5B7FF" stop-opacity="0"/>
</linearGradient>
<radialGradient id="paint1_radial_9588_57903" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(229.979 277.075) rotate(-138.034) scale(294.445 240.743)">
<stop stop-color="#E2DBFF"/>
<stop offset="1" stop-color="#6D4AFF"/>
</radialGradient>
<clipPath id="clip0_9588_57903">
<rect width="256" height="256" fill="white"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

@ -8,4 +8,4 @@ Icon=protonmail-bridge
Exec=protonmail-bridge Exec=protonmail-bridge
Terminal=false Terminal=false
Categories=Office;Email;Network Categories=Office;Email;Network
StartupWMClass=protonmail-bridge StartupWMClass=Proton Mail Bridge

BIN
dist/raw/mac_icon_128x128.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
dist/raw/mac_icon_128x128@2x.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

BIN
dist/raw/mac_icon_16x16.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 715 B

BIN
dist/raw/mac_icon_16x16@2x.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

BIN
dist/raw/mac_icon_256x256.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

BIN
dist/raw/mac_icon_256x256@2x.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 135 KiB

BIN
dist/raw/mac_icon_32x32.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
dist/raw/mac_icon_32x32@2x.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

BIN
dist/raw/mac_icon_512x512.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 136 KiB

BIN
dist/raw/mac_icon_512x512@2x.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 494 KiB

32
dist/raw/win+lin_icon_16x16.svg vendored Normal file
View File

@ -0,0 +1,32 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_9588_57915)">
<path d="M7.9607 -0.00488281C3.9452 -0.00488281 0.69043 3.24988 0.69043 7.26539V14.5839C0.69043 15.3619 1.32115 15.9926 2.09919 15.9926H13.9727C14.6674 15.9926 15.231 15.429 15.231 14.7344V7.26539C15.231 3.25041 11.9762 -0.00488281 7.9607 -0.00488281ZM12.1456 7.22502L8.96786 9.90202C8.39429 10.3854 7.55543 10.3854 6.98186 9.90202L3.80416 7.22502C3.80416 4.95329 5.64598 3.11147 7.91771 3.11147H8.032C10.3037 3.11147 12.1456 4.95329 12.1456 7.22502Z" fill="#6D4AFF"/>
<path d="M7.9607 -0.00488281C3.9452 -0.00488281 0.69043 3.24988 0.69043 7.26539V14.5839C0.69043 15.3619 1.32115 15.9926 2.09919 15.9926H13.9727C14.6674 15.9926 15.231 15.429 15.231 14.7344V7.26539C15.231 3.25041 11.9762 -0.00488281 7.9607 -0.00488281ZM12.1456 7.22502L8.96786 9.90202C8.39429 10.3854 7.55543 10.3854 6.98186 9.90202L3.80416 7.22502C3.80416 4.95329 5.64598 3.11147 7.91771 3.11147H8.032C10.3037 3.11147 12.1456 4.95329 12.1456 7.22502Z" fill="url(#paint0_linear_9588_57915)"/>
<g filter="url(#filter0_i_9588_57915)">
<path d="M8.97323 9.93257C8.64192 10.2008 7.78051 10.5763 6.98537 9.93257C6.19022 9.28888 4.53998 7.86583 3.81426 7.23476H3.81805L3.80416 7.22306C3.80416 4.95133 5.64598 3.10952 7.91771 3.10952H8.032C10.3037 3.10952 12.1456 4.95133 12.1456 7.22306L12.1317 7.23476H12.1443V15.9907H13.9727C14.6674 15.9907 15.231 15.4271 15.231 14.7324V7.26343C15.231 3.24845 11.9762 -0.00683594 7.9607 -0.00683594C3.9452 -0.00683594 0.69043 3.24793 0.69043 7.26343V7.72306L5.18683 11.5891C5.51814 11.9047 6.38901 12.3464 7.22202 11.5891C8.05502 10.8318 8.73658 10.1692 8.97323 9.93257Z" fill="url(#paint1_radial_9588_57915)"/>
</g>
</g>
<defs>
<filter id="filter0_i_9588_57915" x="0.455905" y="-0.00683594" width="14.7755" height="16.6514" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="-0.234525" dy="0.654324"/>
<feGaussianBlur stdDeviation="1.75894"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.462745 0 0 0 0 0.337255 0 0 0 0 1 0 0 0 0.24 0"/>
<feBlend mode="normal" in2="shape" result="effect1_innerShadow_9588_57915"/>
</filter>
<linearGradient id="paint0_linear_9588_57915" x1="1.21106" y1="17.8385" x2="3.38824" y2="11.6856" gradientUnits="userSpaceOnUse">
<stop stop-color="#28B0E8"/>
<stop offset="1" stop-color="#C5B7FF" stop-opacity="0"/>
</linearGradient>
<radialGradient id="paint1_radial_9588_57915" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(14.3736 17.3159) rotate(-138.034) scale(18.4028 15.0465)">
<stop stop-color="#E2DBFF"/>
<stop offset="1" stop-color="#6D4AFF"/>
</radialGradient>
<clipPath id="clip0_9588_57915">
<rect width="16" height="16" fill="white"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 3.1 KiB

32
dist/raw/win+lin_icon_24x24.svg vendored Normal file
View File

@ -0,0 +1,32 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_9588_57912)">
<path d="M11.8651 -0.0078125C6.09279 -0.0078125 1.41406 4.67091 1.41406 10.4432V20.9636C1.41406 22.082 2.32072 22.9886 3.43915 22.9886H20.5073C21.5059 22.9886 22.3161 22.1785 22.3161 21.1799V10.4432C22.3161 4.67167 17.6374 -0.0078125 11.8651 -0.0078125ZM17.8808 10.3852L13.3129 14.2334C12.4884 14.9282 11.2825 14.9282 10.458 14.2334L5.89005 10.3852C5.89005 7.11956 8.53767 4.47195 11.8033 4.47195H11.9676C15.2332 4.47195 17.8808 7.11956 17.8808 10.3852Z" fill="#6D4AFF"/>
<path d="M11.8651 -0.0078125C6.09279 -0.0078125 1.41406 4.67091 1.41406 10.4432V20.9636C1.41406 22.082 2.32072 22.9886 3.43915 22.9886H20.5073C21.5059 22.9886 22.3161 22.1785 22.3161 21.1799V10.4432C22.3161 4.67167 17.6374 -0.0078125 11.8651 -0.0078125ZM17.8808 10.3852L13.3129 14.2334C12.4884 14.9282 11.2825 14.9282 10.458 14.2334L5.89005 10.3852C5.89005 7.11956 8.53767 4.47195 11.8033 4.47195H11.9676C15.2332 4.47195 17.8808 7.11956 17.8808 10.3852Z" fill="url(#paint0_linear_9588_57912)"/>
<g filter="url(#filter0_i_9588_57912)">
<path d="M13.3213 14.28C12.8451 14.6656 11.6068 15.2053 10.4638 14.28C9.32078 13.3547 6.94856 11.3091 5.90533 10.4019H5.91095L5.89103 10.3852C5.89103 7.11956 8.53864 4.47195 11.8043 4.47195H11.9686C15.2342 4.47195 17.8818 7.11956 17.8818 10.3852L17.8619 10.4019H17.8798V22.9886H20.5083C21.5069 22.9886 22.3171 22.1785 22.3171 21.1799V10.4432C22.3171 4.67167 17.6383 -0.0078125 11.8661 -0.0078125C6.09377 -0.0078125 1.41504 4.67091 1.41504 10.4432V11.1041L7.8784 16.6613C8.35466 17.1149 9.60653 17.7499 10.804 16.6613C12.0014 15.5727 12.9812 14.6202 13.3213 14.28Z" fill="url(#paint1_radial_9588_57912)"/>
</g>
</g>
<defs>
<filter id="filter0_i_9588_57912" x="1.07791" y="-0.0078125" width="21.2395" height="23.9367" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="-0.337129" dy="0.940591"/>
<feGaussianBlur stdDeviation="2.52847"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.462745 0 0 0 0 0.337255 0 0 0 0 1 0 0 0 0.24 0"/>
<feBlend mode="normal" in2="shape" result="effect1_innerShadow_9588_57912"/>
</filter>
<linearGradient id="paint0_linear_9588_57912" x1="2.16247" y1="25.6421" x2="5.29216" y2="16.7973" gradientUnits="userSpaceOnUse">
<stop stop-color="#28B0E8"/>
<stop offset="1" stop-color="#C5B7FF" stop-opacity="0"/>
</linearGradient>
<radialGradient id="paint1_radial_9588_57912" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(21.0847 24.8937) rotate(-138.034) scale(26.454 21.6293)">
<stop stop-color="#E2DBFF"/>
<stop offset="1" stop-color="#6D4AFF"/>
</radialGradient>
<clipPath id="clip0_9588_57912">
<rect width="24" height="24" fill="white"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 3.1 KiB

BIN
dist/raw/win+lin_icon_256x256.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

32
dist/raw/win+lin_icon_256x256.svg vendored Normal file
View File

@ -0,0 +1,32 @@
<svg width="256" height="256" viewBox="0 0 256 256" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_9588_57903)">
<path d="M127.416 -0.0898438C63.1423 -0.0898438 11.0449 51.9864 11.0449 116.234V233.331C11.0449 245.779 21.1405 255.871 33.5942 255.871H223.647C234.767 255.871 243.788 246.853 243.788 235.738V116.234C243.788 51.9948 191.691 -0.0898438 127.416 -0.0898438ZM194.401 115.589L143.537 158.421C134.357 166.155 120.929 166.155 111.749 158.421L60.8849 115.589C60.8849 79.2409 90.3659 49.7718 126.728 49.7718H128.558C164.92 49.7718 194.401 79.2409 194.401 115.589Z" fill="#6D4AFF"/>
<path d="M127.416 -0.0898438C63.1423 -0.0898438 11.0449 51.9864 11.0449 116.234V233.331C11.0449 245.779 21.1405 255.871 33.5942 255.871H223.647C234.767 255.871 243.788 246.853 243.788 235.738V116.234C243.788 51.9948 191.691 -0.0898438 127.416 -0.0898438ZM194.401 115.589L143.537 158.421C134.357 166.155 120.929 166.155 111.749 158.421L60.8849 115.589C60.8849 79.2409 90.3659 49.7718 126.728 49.7718H128.558C164.92 49.7718 194.401 79.2409 194.401 115.589Z" fill="url(#paint0_linear_9588_57903)"/>
<g filter="url(#filter0_i_9588_57903)">
<path d="M143.572 158.939C138.271 163.23 124.489 169.238 111.766 158.939C99.0439 148.64 72.6401 125.871 61.0285 115.774H61.0868L60.8676 115.59C60.8676 79.2418 90.3367 49.7728 126.684 49.7728H128.513C164.861 49.7728 194.33 79.2418 194.33 115.59L194.111 115.774H194.31V255.872H223.564C234.679 255.872 243.697 246.854 243.697 235.739V116.235C243.697 51.9958 191.62 -0.0888672 127.372 -0.0888672C63.1241 -0.0888672 11.0479 51.9874 11.0479 116.235V123.587L82.9896 185.444C88.2906 190.492 102.224 197.56 115.553 185.444C128.881 173.327 139.786 162.726 143.572 158.939Z" fill="url(#paint1_radial_9588_57903)"/>
</g>
</g>
<defs>
<filter id="filter0_i_9588_57903" x="7.29545" y="-0.0888672" width="236.401" height="266.43" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="-3.7524" dy="10.4692"/>
<feGaussianBlur stdDeviation="28.143"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.462745 0 0 0 0 0.337255 0 0 0 0 1 0 0 0 0.24 0"/>
<feBlend mode="normal" in2="shape" result="effect1_innerShadow_9588_57903"/>
</filter>
<linearGradient id="paint0_linear_9588_57903" x1="19.3784" y1="285.405" x2="54.2022" y2="186.949" gradientUnits="userSpaceOnUse">
<stop stop-color="#28B0E8"/>
<stop offset="1" stop-color="#C5B7FF" stop-opacity="0"/>
</linearGradient>
<radialGradient id="paint1_radial_9588_57903" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(229.979 277.075) rotate(-138.034) scale(294.445 240.743)">
<stop stop-color="#E2DBFF"/>
<stop offset="1" stop-color="#6D4AFF"/>
</radialGradient>
<clipPath id="clip0_9588_57903">
<rect width="256" height="256" fill="white"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 3.1 KiB

32
dist/raw/win+lin_icon_32x32.svg vendored Normal file
View File

@ -0,0 +1,32 @@
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_9588_57909)">
<path d="M15.9709 -0.0107422C8.19088 -0.0107422 1.88477 6.29537 1.88477 14.0754V28.255C1.88477 29.7625 3.10678 30.9845 4.61423 30.9845H27.6191C28.9651 30.9845 30.0571 29.8925 30.0571 28.5465V14.0754C30.0571 6.29638 23.751 -0.0107422 15.9709 -0.0107422ZM24.0791 13.9972L17.9223 19.1839C16.811 20.1205 15.1857 20.1205 14.0744 19.1839L7.91762 13.9972C7.91762 9.59571 11.4861 6.02719 15.8876 6.02719H16.1091C20.5105 6.02719 24.0791 9.59571 24.0791 13.9972Z" fill="#6D4AFF"/>
<path d="M15.9709 -0.0107422C8.19088 -0.0107422 1.88477 6.29537 1.88477 14.0754V28.255C1.88477 29.7625 3.10678 30.9845 4.61423 30.9845H27.6191C28.9651 30.9845 30.0571 29.8925 30.0571 28.5465V14.0754C30.0571 6.29638 23.751 -0.0107422 15.9709 -0.0107422ZM24.0791 13.9972L17.9223 19.1839C16.811 20.1205 15.1857 20.1205 14.0744 19.1839L7.91762 13.9972C7.91762 9.59571 11.4861 6.02719 15.8876 6.02719H16.1091C20.5105 6.02719 24.0791 9.59571 24.0791 13.9972Z" fill="url(#paint0_linear_9588_57909)"/>
<g filter="url(#filter0_i_9588_57909)">
<path d="M17.9322 19.2467C17.2903 19.7663 15.6213 20.4938 14.0807 19.2467C12.5401 17.9996 9.34279 15.2424 7.9367 14.0197H7.94435L7.91762 13.9972C7.91762 9.59571 11.4861 6.02719 15.8876 6.02719H16.1091C20.5105 6.02719 24.0791 9.59571 24.0791 13.9972L24.0523 14.0197H24.0762V30.9845H27.6191C28.9651 30.9845 30.0571 29.8925 30.0571 28.5465V14.0754C30.0571 6.29638 23.751 -0.0107422 15.9709 -0.0107422C8.19088 -0.0107422 1.88477 6.29537 1.88477 14.0754V14.9662L10.596 22.4563C11.238 23.0676 12.9253 23.9235 14.5392 22.4563C16.1532 20.989 17.4737 19.7052 17.9322 19.2467Z" fill="url(#paint1_radial_9588_57909)"/>
</g>
</g>
<defs>
<filter id="filter0_i_9588_57909" x="1.43037" y="-0.0107422" width="28.6263" height="32.2629" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="-0.454392" dy="1.26775"/>
<feGaussianBlur stdDeviation="3.40794"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.462745 0 0 0 0 0.337255 0 0 0 0 1 0 0 0 0.24 0"/>
<feBlend mode="normal" in2="shape" result="effect1_innerShadow_9588_57909"/>
</filter>
<linearGradient id="paint0_linear_9588_57909" x1="2.89348" y1="34.5608" x2="7.11177" y2="22.6396" gradientUnits="userSpaceOnUse">
<stop stop-color="#28B0E8"/>
<stop offset="1" stop-color="#C5B7FF" stop-opacity="0"/>
</linearGradient>
<radialGradient id="paint1_radial_9588_57909" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(28.396 33.5521) rotate(-138.034) scale(35.6554 29.1525)">
<stop stop-color="#E2DBFF"/>
<stop offset="1" stop-color="#6D4AFF"/>
</radialGradient>
<clipPath id="clip0_9588_57909">
<rect width="32" height="32" fill="white"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 3.1 KiB

32
dist/raw/win+lin_icon_48x48.svg vendored Normal file
View File

@ -0,0 +1,32 @@
<svg width="48" height="48" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_9588_57906)">
<path d="M23.8921 -0.0166016C11.9792 -0.0166016 2.32324 9.63938 2.32324 21.5523V43.2642C2.32324 45.5724 4.1944 47.4436 6.50263 47.4436H41.728C43.7889 47.4436 45.461 45.7715 45.461 43.7106V21.5523C45.461 9.64093 35.805 -0.0166016 23.8921 -0.0166016ZM36.3074 21.4325L26.8801 29.3744C25.1784 30.8085 22.6898 30.8085 20.9882 29.3744L11.5608 21.4325C11.5608 14.6929 17.025 9.22875 23.7646 9.22875H24.1036C30.8432 9.22875 36.3074 14.6929 36.3074 21.4325Z" fill="#6D4AFF"/>
<path d="M23.8921 -0.0166016C11.9792 -0.0166016 2.32324 9.63938 2.32324 21.5523V43.2642C2.32324 45.5724 4.1944 47.4436 6.50263 47.4436H41.728C43.7889 47.4436 45.461 45.7715 45.461 43.7106V21.5523C45.461 9.64093 35.805 -0.0166016 23.8921 -0.0166016ZM36.3074 21.4325L26.8801 29.3744C25.1784 30.8085 22.6898 30.8085 20.9882 29.3744L11.5608 21.4325C11.5608 14.6929 17.025 9.22875 23.7646 9.22875H24.1036C30.8432 9.22875 36.3074 14.6929 36.3074 21.4325Z" fill="url(#paint0_linear_9588_57906)"/>
<g filter="url(#filter0_i_9588_57906)">
<path d="M26.8954 29.4706C25.9125 30.2663 23.3569 31.3803 20.998 29.4706C18.639 27.561 13.7432 23.3392 11.5902 21.467H11.6017L11.5608 21.4325C11.5608 14.6929 17.025 9.22875 23.7646 9.22875H24.1036C30.8432 9.22875 36.3074 14.6929 36.3074 21.4325L36.2665 21.467H36.3032V47.4436H41.728C43.7889 47.4436 45.461 45.7715 45.461 43.7106V21.5523C45.461 9.64093 35.805 -0.0166016 23.8921 -0.0166016C11.9792 -0.0166016 2.32324 9.63938 2.32324 21.5523V22.9161L15.6622 34.3851C16.6451 35.3212 19.2287 36.6318 21.7 34.3851C24.1713 32.1385 26.1933 30.1727 26.8954 29.4706Z" fill="url(#paint1_radial_9588_57906)"/>
</g>
</g>
<defs>
<filter id="filter0_i_9588_57906" x="1.62747" y="-0.0166016" width="43.8335" height="49.4012" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="-0.69577" dy="1.9412"/>
<feGaussianBlur stdDeviation="5.21827"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.462745 0 0 0 0 0.337255 0 0 0 0 1 0 0 0 0.24 0"/>
<feBlend mode="normal" in2="shape" result="effect1_innerShadow_9588_57906"/>
</filter>
<linearGradient id="paint0_linear_9588_57906" x1="3.8678" y1="52.9198" x2="10.3269" y2="34.6659" gradientUnits="userSpaceOnUse">
<stop stop-color="#28B0E8"/>
<stop offset="1" stop-color="#C5B7FF" stop-opacity="0"/>
</linearGradient>
<radialGradient id="paint1_radial_9588_57906" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(42.9175 51.3752) rotate(-138.034) scale(54.5959 44.6386)">
<stop stop-color="#E2DBFF"/>
<stop offset="1" stop-color="#6D4AFF"/>
</radialGradient>
<clipPath id="clip0_9588_57906">
<rect width="48" height="48" fill="white"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 3.0 KiB

16
go.mod
View File

@ -7,19 +7,19 @@ go 1.15
require ( require (
github.com/docker/docker-credential-helpers v0.6.3 github.com/docker/docker-credential-helpers v0.6.3
github.com/emersion/go-imap v1.0.6 github.com/emersion/go-imap v1.0.6
github.com/jameskeane/bcrypt v0.0.0-20170924085257-7509ea014998 // indirect
) )
require ( require (
github.com/0xAX/notificator v0.0.0-20191016112426-3962a5ea8da1 github.com/0xAX/notificator v0.0.0-20191016112426-3962a5ea8da1
github.com/Masterminds/semver/v3 v3.1.0 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-autostart v0.0.0-20181114175602-c5272053443a
github.com/ProtonMail/go-crypto v0.0.0-20211221144345-a4f6767435ab 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-imap-id v0.0.0-20190926060100-f94a56b9ecde
github.com/ProtonMail/go-rfc5322 v0.8.0 github.com/ProtonMail/go-rfc5322 v0.8.0
github.com/ProtonMail/go-srp v0.0.1 github.com/ProtonMail/go-srp v0.0.5
github.com/ProtonMail/go-vcard v0.0.0-20180326232728-33aaa0a0c8a5 github.com/ProtonMail/go-vcard v0.0.0-20180326232728-33aaa0a0c8a5
github.com/ProtonMail/gopenpgp/v2 v2.4.1 github.com/ProtonMail/gopenpgp/v2 v2.4.7
github.com/PuerkitoBio/goquery v1.5.1 github.com/PuerkitoBio/goquery v1.5.1
github.com/abiosoft/ishell v2.0.0+incompatible github.com/abiosoft/ishell v2.0.0+incompatible
github.com/abiosoft/readline v0.0.0-20180607040430-155bce2042db // indirect github.com/abiosoft/readline v0.0.0-20180607040430-155bce2042db // indirect
@ -48,6 +48,7 @@ require (
github.com/google/go-cmp v0.5.5 github.com/google/go-cmp v0.5.5
github.com/google/uuid v1.1.1 github.com/google/uuid v1.1.1
github.com/hashicorp/go-multierror v1.1.0 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/jaytaylor/html2text v0.0.0-20200412013138-3577fbdbcff7
github.com/keybase/go-keychain v0.0.0 github.com/keybase/go-keychain v0.0.0
github.com/kr/text v0.2.0 // indirect github.com/kr/text v0.2.0 // indirect
@ -69,17 +70,16 @@ require (
github.com/urfave/cli/v2 v2.2.0 github.com/urfave/cli/v2 v2.2.0
github.com/vmihailenco/msgpack/v5 v5.1.3 github.com/vmihailenco/msgpack/v5 v5.1.3
go.etcd.io/bbolt v1.3.6 go.etcd.io/bbolt v1.3.6
golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4 // indirect golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d // indirect
golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4 golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4
golang.org/x/sys v0.0.0-20220111092808-5a964db01320 golang.org/x/sys v0.0.0-20220627191245-f75cf1eec38b
golang.org/x/text v0.3.7 golang.org/x/text v0.3.7
howett.net/plist v1.0.0 // indirect howett.net/plist v1.0.0
) )
replace ( replace (
github.com/docker/docker-credential-helpers => github.com/ProtonMail/docker-credential-helpers v1.1.0 github.com/docker/docker-credential-helpers => github.com/ProtonMail/docker-credential-helpers v1.1.0
github.com/emersion/go-imap => github.com/ProtonMail/go-imap v0.0.0-20201228133358-4db68cea0cac github.com/emersion/go-imap => github.com/ProtonMail/go-imap v0.0.0-20201228133358-4db68cea0cac
github.com/emersion/go-message => github.com/ProtonMail/go-message v0.0.0-20210611055058-fabeff2ec753 github.com/emersion/go-message => github.com/ProtonMail/go-message v0.0.0-20210611055058-fabeff2ec753
github.com/jameskeane/bcrypt => github.com/ProtonMail/bcrypt v0.0.0-20210511135022-227b4adcab57
github.com/keybase/go-keychain => github.com/cuthix/go-keychain v0.0.0-20220405075754-31e7cee908fe github.com/keybase/go-keychain => github.com/cuthix/go-keychain v0.0.0-20220405075754-31e7cee908fe
) )

18
go.sum
View File

@ -24,6 +24,8 @@ github.com/Masterminds/semver/v3 v3.1.0/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= 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 h1:pHA4K54ifoogVLunGGHi3xyF5Nz4x+Uh3dJuy3NwGQQ=
github.com/ProtonMail/bcrypt v0.0.0-20210511135022-227b4adcab57/go.mod h1:HecWFHognK8GfRDGnFQbW/LiV7A3MX3gZVs45vk5h8I= 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 h1:+kvUIpwWcbtP3WFv5sSvkFn/XLzSqPOB5AAthuk9xPk=
github.com/ProtonMail/docker-credential-helpers v1.1.0/go.mod h1:mK0aBveCxhnQ756AmaTfXMZDeULvheYVhF/MWMErN5g= github.com/ProtonMail/docker-credential-helpers v1.1.0/go.mod h1:mK0aBveCxhnQ756AmaTfXMZDeULvheYVhF/MWMErN5g=
github.com/ProtonMail/go-autostart v0.0.0-20181114175602-c5272053443a h1:fXK2KsfnkBV9Nh+9SKzHchYjuE9s0vI20JG1mbtEAcc= github.com/ProtonMail/go-autostart v0.0.0-20181114175602-c5272053443a h1:fXK2KsfnkBV9Nh+9SKzHchYjuE9s0vI20JG1mbtEAcc=
@ -31,6 +33,9 @@ github.com/ProtonMail/go-autostart v0.0.0-20181114175602-c5272053443a/go.mod h1:
github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo= github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo=
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 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-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 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 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 h1:5koQozTDELymYOyFbQ/VSubexAEXzDR8qGM5mO8GRdw=
@ -39,14 +44,20 @@ github.com/ProtonMail/go-message v0.0.0-20210611055058-fabeff2ec753 h1:I8IsYA297
github.com/ProtonMail/go-message v0.0.0-20210611055058-fabeff2ec753/go.mod h1:NBAn21zgCJ/52WLDyed18YvYFm5tEoeDauubFqLokM4= 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 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-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.8.0 h1:7emrf75n3CDIduQflx7aT1nJa5h/kGsiFKUYX/+IAkU= 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-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 h1:J0O9Zb5XTC6iDrB7feH41cu+TUEB+l7uHctXIK6oS2o=
github.com/ProtonMail/go-srp v0.0.1/go.mod h1:Uvv5cqSGCs8MTZ8sbKiCkBnaB6/OA3eq2mc77tl2VVA= 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 h1:Uga1DHFN4GUxuDQr0F71tpi8I9HqPIlZodZAI1lR6VQ=
github.com/ProtonMail/go-vcard v0.0.0-20180326232728-33aaa0a0c8a5/go.mod h1:oeP9CMN+ajWp5jKp1kue5daJNwMMxLF+ujPaUIoJWlA= github.com/ProtonMail/go-vcard v0.0.0-20180326232728-33aaa0a0c8a5/go.mod h1:oeP9CMN+ajWp5jKp1kue5daJNwMMxLF+ujPaUIoJWlA=
github.com/ProtonMail/gopenpgp/v2 v2.4.1 h1:b3El0zabaKi73u4sRnb3hOOUczuKuYpN8wnp7wRsZSc= 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.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 h1:PSPBGne8NIUWw+/7vFBV+kG2J/5MOjbzc7154OaKCSE=
github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc= 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/Shopify/goreferrer v0.0.0-20181106222321-ec9c9a553398/go.mod h1:a1uqRtAwp2Xwc6WNPJEufxJ7fx3npB4UV/JOLmbu5I0=
@ -95,6 +106,8 @@ github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsr
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/cronokirby/saferith v0.31.0 h1:TIlhldetKLeGAb19bZvWiuwQEzfzwSPthDEyJ9Ah8xs= 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.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 h1:mMSKu1077ffLbTJULUfM5HPokgeBcIGboyeNUof1MdE=
github.com/cucumber/gherkin-go/v19 v19.0.3/go.mod h1:jY/NP6jUtRSArQQJ5h1FXOUgk5fZK24qtE7vKi776Vw= github.com/cucumber/gherkin-go/v19 v19.0.3/go.mod h1:jY/NP6jUtRSArQQJ5h1FXOUgk5fZK24qtE7vKi776Vw=
github.com/cucumber/godog v0.12.1 h1:IhWVYFKDReM5WsuA9AuRLRPWOyvFNO9UBUKrNfLPais= github.com/cucumber/godog v0.12.1 h1:IhWVYFKDReM5WsuA9AuRLRPWOyvFNO9UBUKrNfLPais=
@ -249,6 +262,7 @@ github.com/iris-contrib/go.uuid v2.0.0+incompatible/go.mod h1:iz2lgM/1UnEf1kP0L/
github.com/iris-contrib/jade v1.1.3/go.mod h1:H/geBymxJhShH5kecoiOCSssPX7QWYH7UaeZTSWddIk= 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/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/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 h1:g0fAGBisHaEQ0TRq1iBvemFRf+8AEWEmBESSiWB3Vsc=
github.com/jaytaylor/html2text v0.0.0-20200412013138-3577fbdbcff7/go.mod h1:CVKlgaMiht+LXvHG173ujK6JUhZXKb2u/BQtjPDIvyk= 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/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
@ -473,6 +487,8 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 h1:7I4JAnoQBe7ZtJcBaYHi5U
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= 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 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-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-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-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-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@ -575,6 +591,8 @@ golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e h1:fLOSk5Q00efkSvAm+4xcoXD+R
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220111092808-5a964db01320 h1:0jf+tOCoZ3LyutmCOWpVni1chK4VfFLhRsDK7MhqGRY= 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-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-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 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 945 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

View File

@ -24,6 +24,7 @@ package api
import ( import (
"fmt" "fmt"
"net/http" "net/http"
"time"
"github.com/ProtonMail/proton-bridge/v2/internal/bridge" "github.com/ProtonMail/proton-bridge/v2/internal/bridge"
"github.com/ProtonMail/proton-bridge/v2/internal/config/settings" "github.com/ProtonMail/proton-bridge/v2/internal/config/settings"
@ -57,8 +58,9 @@ func (api *apiServer) ListenAndServe() {
addr := api.getAddress() addr := api.getAddress()
server := &http.Server{ server := &http.Server{
Addr: addr, Addr: addr,
Handler: mux, 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).
} }
log.Info("API listening at ", addr) log.Info("API listening at ", addr)

View File

@ -57,7 +57,6 @@ import (
"github.com/ProtonMail/proton-bridge/v2/pkg/keychain" "github.com/ProtonMail/proton-bridge/v2/pkg/keychain"
"github.com/ProtonMail/proton-bridge/v2/pkg/listener" "github.com/ProtonMail/proton-bridge/v2/pkg/listener"
"github.com/ProtonMail/proton-bridge/v2/pkg/pmapi" "github.com/ProtonMail/proton-bridge/v2/pkg/pmapi"
"github.com/allan-simon/go-singleinstance"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
) )
@ -153,9 +152,9 @@ func New( //nolint:funlen
} }
settingsObj := settings.New(settingsPath) settingsObj := settings.New(settingsPath)
lock, err := singleinstance.CreateLockFile(locations.GetLockFile()) lock, err := checkSingleInstance(locations.GetLockFile(), settingsObj)
if err != nil { if err != nil {
logrus.Warnf("%v is already running", appName) logrus.WithError(err).Warnf("%v is already running", appName)
return nil, api.CheckOtherInstanceAndFocus(settingsObj.GetInt(settings.APIPortKey)) return nil, api.CheckOtherInstanceAndFocus(settingsObj.GetInt(settings.APIPortKey))
} }

View File

@ -19,10 +19,10 @@ package base
import ( import (
"os" "os"
"os/exec"
"strconv" "strconv"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"golang.org/x/sys/execabs"
) )
// maxAllowedRestarts controls after how many crashes the app will give up restarting. // maxAllowedRestarts controls after how many crashes the app will give up restarting.
@ -43,7 +43,7 @@ func (b *Base) restartApp(crash bool) error {
WithField("args", args). WithField("args", args).
Warn("Restarting") Warn("Restarting")
return exec.Command(b.command, args...).Start() //nolint:gosec return execabs.Command(b.command, args...).Start() //nolint:gosec
} }
// incrementRestartFlag increments the value of the restart flag. // incrementRestartFlag increments the value of the restart flag.

View File

@ -21,7 +21,9 @@ import (
"strings" "strings"
"testing" "testing"
"github.com/Masterminds/semver/v3"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
) )
func TestIncrementRestartFlag(t *testing.T) { func TestIncrementRestartFlag(t *testing.T) {
@ -47,3 +49,15 @@ func TestIncrementRestartFlag(t *testing.T) {
}) })
} }
} }
func TestVersionLessThan(t *testing.T) {
r := require.New(t)
old := semver.MustParse("1.1.0")
current := semver.MustParse("1.1.1")
newer := semver.MustParse("1.1.2")
r.True(old.LessThan(current))
r.False(current.LessThan(current))
r.False(newer.LessThan(current))
}

View File

@ -0,0 +1,101 @@
// 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/>.
//go:build !windows
// +build !windows
package base
import (
"errors"
"os"
"path/filepath"
"strconv"
"strings"
"time"
"github.com/Masterminds/semver/v3"
"github.com/ProtonMail/proton-bridge/v2/internal/config/settings"
"github.com/ProtonMail/proton-bridge/v2/internal/constants"
"github.com/allan-simon/go-singleinstance"
"golang.org/x/sys/unix"
)
// checkSingleInstance returns error if a bridge instance is already running
// This instance should be stop and window of running window should be brought
// to focus.
//
// For macOS and Linux when already running version is older than this instance
// it will kill old and continue with this new bridge (i.e. no error returned).
func checkSingleInstance(lockFilePath string, settingsObj *settings.Settings) (*os.File, error) {
if lock, err := singleinstance.CreateLockFile(lockFilePath); err == nil {
// Bridge is not runnig, continue normally
return lock, nil
}
if err := runningVersionIsOlder(settingsObj); err != nil {
return nil, err
}
pid, err := getPID(lockFilePath)
if err != nil {
return nil, err
}
if err := unix.Kill(pid, unix.SIGTERM); err != nil {
return nil, err
}
// Need to wait some time to release file lock
time.Sleep(time.Second)
return singleinstance.CreateLockFile(lockFilePath)
}
func getPID(lockFilePath string) (int, error) {
file, err := os.Open(filepath.Clean(lockFilePath))
if err != nil {
return 0, err
}
defer func() { _ = file.Close() }()
rawPID := make([]byte, 10) // PID is probably up to 7 digits long, 10 should be enough
n, err := file.Read(rawPID)
if err != nil {
return 0, err
}
return strconv.Atoi(strings.TrimSpace(string(rawPID[:n])))
}
func runningVersionIsOlder(settingsObj *settings.Settings) error {
currentVer, err := semver.StrictNewVersion(constants.Version)
if err != nil {
return err
}
runningVer, err := semver.StrictNewVersion(settingsObj.Get(settings.LastVersionKey))
if err != nil {
return err
}
if !runningVer.LessThan(currentVer) {
return errors.New("running version is not older")
}
return nil
}

View File

@ -0,0 +1,32 @@
// 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/>.
//go:build windows
// +build windows
package base
import (
"os"
"github.com/ProtonMail/proton-bridge/v2/internal/config/settings"
"github.com/allan-simon/go-singleinstance"
)
func checkSingleInstance(lockFilePath string, _ *settings.Settings) (*os.File, error) {
return singleinstance.CreateLockFile(lockFilePath)
}

View File

@ -57,8 +57,9 @@ type Bridge struct {
// Bridge's global errors list. // Bridge's global errors list.
errors []error errors []error
isFirstStart bool isAllMailVisible bool
lastVersion string isFirstStart bool
lastVersion string
} }
func New( func New(
@ -92,15 +93,16 @@ func New(
) )
b := &Bridge{ b := &Bridge{
Users: u, Users: u,
locations: locations, locations: locations,
settings: setting, settings: setting,
clientManager: clientManager, clientManager: clientManager,
updater: updater, updater: updater,
versioner: versioner, versioner: versioner,
cacheProvider: cacheProvider, cacheProvider: cacheProvider,
autostart: autostart, autostart: autostart,
isFirstStart: false, isFirstStart: false,
isAllMailVisible: setting.GetBool(settings.IsAllMailVisible),
} }
if setting.GetBool(settings.FirstStartKey) { if setting.GetBool(settings.FirstStartKey) {
@ -302,3 +304,14 @@ func (b *Bridge) GetLastVersion() string {
func (b *Bridge) IsFirstStart() bool { func (b *Bridge) IsFirstStart() bool {
return b.isFirstStart 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
}

View File

@ -55,6 +55,7 @@ const (
AttachmentWorkers = "attachment_workers" AttachmentWorkers = "attachment_workers"
ColorScheme = "color_scheme" ColorScheme = "color_scheme"
RebrandingMigrationKey = "rebranding_migrated" RebrandingMigrationKey = "rebranding_migrated"
IsAllMailVisible = "is_all_mail_visible"
) )
type Settings struct { type Settings struct {
@ -110,4 +111,6 @@ func (s *Settings) setDefaultValues() {
// By default, stick to STARTTLS. If the user uses catalina+applemail they'll have to change to SSL. // By default, stick to STARTTLS. If the user uses catalina+applemail they'll have to change to SSL.
s.setDefault(SMTPSSLKey, "false") s.setDefault(SMTPSSLKey, "false")
s.setDefault(IsAllMailVisible, "true")
} }

View File

@ -17,10 +17,10 @@
package tls package tls
import "os/exec" import "golang.org/x/sys/execabs"
func addTrustedCert(certPath string) error { func addTrustedCert(certPath string) error {
return exec.Command( //nolint:gosec return execabs.Command( //nolint:gosec
"/usr/bin/security", "/usr/bin/security",
"execute-with-privileges", "execute-with-privileges",
"/usr/bin/security", "/usr/bin/security",
@ -34,7 +34,7 @@ func addTrustedCert(certPath string) error {
} }
func removeTrustedCert(certPath string) error { func removeTrustedCert(certPath string) error {
return exec.Command( //nolint:gosec return execabs.Command( //nolint:gosec
"/usr/bin/security", "/usr/bin/security",
"execute-with-privileges", "execute-with-privileges",
"/usr/bin/security", "/usr/bin/security",

View File

@ -18,37 +18,42 @@
package useragent package useragent
import ( import (
"os/exec"
"runtime" "runtime"
"strings" "strings"
"github.com/Masterminds/semver/v3" "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 { func IsCatalinaOrNewer() bool {
return isThisDarwinNewerOrEqual(getMinCatalina()) 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 { func IsBigSurOrNewer() bool {
return isThisDarwinNewerOrEqual(getMinBigSur()) return isThisDarwinNewerOrEqual(getMinBigSur())
} }
func getMinCatalina() *semver.Version { return semver.MustParse("10.15.0") } // IsVenturaOrNewer checks whether the host is macOS BigSur 13.x or higher.
func getMinBigSur() *semver.Version { return semver.MustParse("10.16.0") } 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 { func isThisDarwinNewerOrEqual(minVersion *semver.Version) bool {
if runtime.GOOS != "darwin" { if runtime.GOOS != "darwin" {
return false return false
} }
rawVersion, err := exec.Command("sw_vers", "-productVersion").Output() rawVersion, err := getDarwinVersion()
if err != nil { if err != nil {
return false return false
} }
return isVersionEqualOrNewer(minVersion, strings.TrimSpace(string(rawVersion))) return isVersionEqualOrNewer(minVersion, strings.TrimSpace(rawVersion))
} }
// isVersionEqualOrNewer is separated to be able to run test on other than darwin. // isVersionEqualOrNewer is separated to be able to run test on other than darwin.

View File

@ -15,20 +15,15 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
package cache //go:build darwin
// +build darwin
package useragent
import ( import (
"crypto/sha256" "syscall"
"encoding/hex"
) )
func getHash(name string) string { func getDarwinVersion() (string, error) {
hash := sha256.New() return syscall.Sysctl("kern.osrelease")
if _, err := hash.Write([]byte(name)); err != nil {
// sha256.Write always returns nill err so this should never happen
panic(err)
}
return hex.EncodeToString(hash.Sum(nil))
} }

View File

@ -0,0 +1,27 @@
// 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/>.
//go:build !darwin
// +build !darwin
package useragent
import "errors"
func getDarwinVersion() (string, error) {
return "", errors.New("implemented only for darwin")
}

View File

@ -25,16 +25,11 @@ import (
func TestIsVersionCatalinaOrNewer(t *testing.T) { func TestIsVersionCatalinaOrNewer(t *testing.T) {
testData := map[struct{ version string }]bool{ testData := map[struct{ version string }]bool{
{""}: false, {""}: false,
{"9.0.0"}: false, {"18.0.0"}: false,
{"9.15.0"}: false, {"19.0.0"}: true,
{"10.13.0"}: false, {"20.0.0"}: true,
{"10.14.0"}: false, {"21.0.0"}: true,
{"10.14.99"}: false,
{"10.15.0"}: true,
{"10.16.0"}: true,
{"11.0.0"}: true,
{"11.1"}: true,
} }
for args, exp := range testData { for args, exp := range testData {
@ -45,16 +40,11 @@ func TestIsVersionCatalinaOrNewer(t *testing.T) {
func TestIsVersionBigSurOrNewer(t *testing.T) { func TestIsVersionBigSurOrNewer(t *testing.T) {
testData := map[struct{ version string }]bool{ testData := map[struct{ version string }]bool{
{""}: false, {""}: false,
{"9.0.0"}: false, {"18.0.0"}: false,
{"9.15.0"}: false, {"19.0.0"}: false,
{"10.13.0"}: false, {"20.0.0"}: true,
{"10.14.0"}: false, {"21.0.0"}: true,
{"10.14.99"}: false,
{"10.15.0"}: false,
{"10.16.0"}: true,
{"11.0.0"}: true,
{"11.1"}: true,
} }
for args, exp := range testData { for args, exp := range testData {

View File

@ -137,6 +137,23 @@ func New( //nolint:funlen
}) })
fe.AddCmd(dohCmd) fe.AddCmd(dohCmd)
// All mail visibility commands.
allMailCmd := &ishell.Cmd{
Name: "all-mail-visibility",
Help: "choose not to list the All Mail folder in your local client",
}
allMailCmd.AddCmd(&ishell.Cmd{
Name: "hide",
Help: "All Mail folder will not be listed in your local client",
Func: fe.hideAllMail,
})
allMailCmd.AddCmd(&ishell.Cmd{
Name: "show",
Help: "All Mail folder will be listed in your local client",
Func: fe.showAllMail,
})
fe.AddCmd(allMailCmd)
// Cache-On-Disk commands. // Cache-On-Disk commands.
codCmd := &ishell.Cmd{ codCmd := &ishell.Cmd{
Name: "local-cache", Name: "local-cache",

View File

@ -152,6 +152,32 @@ func (f *frontendCLI) disallowProxy(c *ishell.Context) {
} }
} }
func (f *frontendCLI) hideAllMail(c *ishell.Context) {
if !f.bridge.IsAllMailVisible() {
f.Println("All Mail folder is not listed in your local client.")
return
}
f.Println("All Mail folder is listed in your client right now.")
if f.yesNoQuestion("Do you want to hide All Mail folder") {
f.bridge.SetIsAllMailVisible(false)
}
}
func (f *frontendCLI) showAllMail(c *ishell.Context) {
if f.bridge.IsAllMailVisible() {
f.Println("All Mail folder is listed in your local client.")
return
}
f.Println("All Mail folder is not listed in your client right now.")
if f.yesNoQuestion("Do you want to show All Mail folder") {
f.bridge.SetIsAllMailVisible(true)
}
}
func (f *frontendCLI) enableCacheOnDisk(c *ishell.Context) { func (f *frontendCLI) enableCacheOnDisk(c *ishell.Context) {
if f.settings.GetBool(settings.CacheEnabledKey) { if f.settings.GetBool(settings.CacheEnabledKey) {
f.Println("The local cache is already enabled.") f.Println("The local cache is already enabled.")

View File

@ -23,7 +23,6 @@ package clientconfig
import ( import (
"io/ioutil" "io/ioutil"
"os" "os"
"os/exec"
"path/filepath" "path/filepath"
"strconv" "strconv"
"strings" "strings"
@ -33,10 +32,12 @@ import (
"github.com/ProtonMail/proton-bridge/v2/internal/config/useragent" "github.com/ProtonMail/proton-bridge/v2/internal/config/useragent"
"github.com/ProtonMail/proton-bridge/v2/internal/frontend/types" "github.com/ProtonMail/proton-bridge/v2/internal/frontend/types"
"github.com/ProtonMail/proton-bridge/v2/pkg/mobileconfig" "github.com/ProtonMail/proton-bridge/v2/pkg/mobileconfig"
"golang.org/x/sys/execabs"
) )
const ( const (
bigSurPreferncesPane = "/System/Library/PreferencePanes/Profiles.prefPane" bigSurPreferencesPane = "/System/Library/PreferencePanes/Profiles.prefPane"
venturaPreferencesPane = "x-apple.systempreferences:com.apple.preferences.configurationprofiles"
) )
func init() { //nolint:gochecknoinit func init() { //nolint:gochecknoinit
@ -56,10 +57,16 @@ func (c *appleMail) Configure(imapPort, smtpPort int, imapSSL, smtpSSL bool, use
} }
if useragent.IsBigSurOrNewer() { if useragent.IsBigSurOrNewer() {
return exec.Command("open", bigSurPreferncesPane, confPath).Run() //nolint:gosec G204: open command is safe, mobileconfig is generated by us prefPane := bigSurPreferencesPane
if useragent.IsVenturaOrNewer() {
prefPane = venturaPreferencesPane
}
return execabs.Command("open", prefPane, confPath).Run() //nolint:gosec // G204 open command is safe, mobileconfig is generated by us
} }
return exec.Command("open", confPath).Run() //nolint:gosec G204: open command is safe, mobileconfig is generated by us return execabs.Command("open", confPath).Run() //nolint:gosec G204: open command is safe, mobileconfig is generated by us
} }
func prepareMobileConfig(imapPort, smtpPort int, imapSSL, smtpSSL bool, user types.User, address string) *mobileconfig.Config { func prepareMobileConfig(imapPort, smtpPort int, imapSSL, smtpSSL bool, user types.User, address string) *mobileconfig.Config {

View File

@ -672,6 +672,10 @@ Window {
Label {colorScheme: root.colorScheme; text: "DoH:"} Label {colorScheme: root.colorScheme; text: "DoH:"}
Toggle {colorScheme: root.colorScheme; checked: root.isDoHEnabled; onClicked: root.isDoHEnabled = !root.isDoHEnabled} Toggle {colorScheme: root.colorScheme; checked: root.isDoHEnabled; onClicked: root.isDoHEnabled = !root.isDoHEnabled}
} }
RowLayout {
Label {colorScheme: root.colorScheme; text: "All Mail disabled:"}
Toggle {colorScheme: root.colorScheme; checked: root.isAllMailVisible; onClicked: root.isAllMailVisible = !root.isAllMailVisible}
}
RowLayout { RowLayout {
Label {colorScheme: root.colorScheme; text: "Ports:"} Label {colorScheme: root.colorScheme; text: "Ports:"}
TextField { TextField {
@ -811,6 +815,13 @@ Window {
root.isDoHEnabled = makeItActive root.isDoHEnabled = makeItActive
} }
property bool isAllMailVisible : true
function changeIsAllMailVisible(isVisible){
console.debug("-> All Mail Visible", isVisible, root.isAllMailVisible)
root.isAllMailVisible = isVisible
}
property bool useSSLforSMTP: false property bool useSSLforSMTP: false
function toggleUseSSLforSMTP(makeItActive){ function toggleUseSSLforSMTP(makeItActive){
console.debug("-> SMTP SSL", makeItActive, root.useSSLforSMTP) console.debug("-> SMTP SSL", makeItActive, root.useSSLforSMTP)

View File

@ -156,6 +156,19 @@ SettingsView {
Layout.fillWidth: true Layout.fillWidth: true
} }
SettingsItem {
id: allMail
visible: root._isAdvancedShown
colorScheme: root.colorScheme
text: qsTr("Show All Mail")
description: qsTr("Choose to list the All Mail folder in your local client.")
type: SettingsItem.Toggle
checked: root.backend.isAllMailVisible
onClicked: root.notifications.askChangeAllMailVisibility(root.backend.isAllMailVisible)
Layout.fillWidth: true
}
SettingsItem { SettingsItem {
id: ports id: ports
visible: root._isAdvancedShown visible: root._isAdvancedShown

View File

@ -110,6 +110,11 @@ Item {
notification: root.notifications.resetBridge notification: root.notifications.resetBridge
} }
NotificationDialog {
colorScheme: root.colorScheme
notification: root.notifications.changeAllMailVisibility
}
NotificationDialog { NotificationDialog {
colorScheme: root.colorScheme colorScheme: root.colorScheme
notification: root.notifications.deleteAccount notification: root.notifications.deleteAccount

View File

@ -34,6 +34,7 @@ QtObject {
signal askDisableLocalCache() signal askDisableLocalCache()
signal askEnableLocalCache(var path) signal askEnableLocalCache(var path)
signal askResetBridge() signal askResetBridge()
signal askChangeAllMailVisibility(var isVisibleNow)
signal askDeleteAccount(var user) signal askDeleteAccount(var user)
enum Group { enum Group {
@ -72,6 +73,7 @@ QtObject {
root.disableLocalCache, root.disableLocalCache,
root.enableLocalCache, root.enableLocalCache,
root.resetBridge, root.resetBridge,
root.changeAllMailVisibility,
root.deleteAccount, root.deleteAccount,
root.noKeychain, root.noKeychain,
root.rebuildKeychain, root.rebuildKeychain,
@ -193,6 +195,7 @@ QtObject {
onTriggered: { onTriggered: {
Qt.openUrlExternally(root.backend.landingPageLink) Qt.openUrlExternally(root.backend.landingPageLink)
root.updateManualError.active = false root.updateManualError.active = false
root.backend.quit()
} }
}, },
Action { Action {
@ -839,6 +842,47 @@ QtObject {
] ]
} }
property Notification changeAllMailVisibility: Notification {
title: root.changeAllMailVisibility.isVisibleNow ?
qsTr("Hide All Mail folder?") :
qsTr("Show All Mail folder?")
brief: title
icon: "./icons/ic-info-circle-filled.svg"
description: qsTr("Switching between showing and hiding the All Mail folder will require you to restart your client.")
type: Notification.NotificationType.Info
group: Notifications.Group.Configuration | Notifications.Group.Dialogs
property var isVisibleNow
Connections {
target: root
onAskChangeAllMailVisibility: {
root.changeAllMailVisibility.isVisibleNow = isVisibleNow
root.changeAllMailVisibility.active = true
}
}
action: [
Action {
id: allMail_change
text: root.changeAllMailVisibility.isVisibleNow ?
qsTr("Hide All Mail folder") :
qsTr("Show All Mail folder")
onTriggered: {
root.backend.changeIsAllMailVisible(!root.changeAllMailVisibility.isVisibleNow)
root.changeAllMailVisibility.active = false
}
},
Action {
id: allMail_cancel
text: qsTr("Cancel")
onTriggered: {
root.changeAllMailVisibility.active = false
}
}
]
}
property Notification deleteAccount: Notification { property Notification deleteAccount: Notification {
title: qsTr("Remove this account?") title: qsTr("Remove this account?")
brief: title brief: title

Binary file not shown.

Before

Width:  |  Height:  |  Size: 64 KiB

After

Width:  |  Height:  |  Size: 74 KiB

View File

@ -5,10 +5,10 @@
viewBox="0 0 265 148" viewBox="0 0 265 148"
fill="none" fill="none"
version="1.1" version="1.1"
id="svg84" id="svg110"
sodipodi:docname="img-welcome-dark.svg" sodipodi:docname="img-welcome-dark.svg"
inkscape:version="1.1.2 (0a00cf5339, 2022-02-04, custom)" inkscape:version="1.1.2 (0a00cf5339, 2022-02-04, custom)"
inkscape:export-filename="/home/dev/gopath/src/github.com/ProtonMail/proton-bridge/v2/internal/frontend/qml/icons/img-welcome.png" inkscape:export-filename="/home/dev/gopath/src/github.com/ProtonMail/proton-bridge/internal/frontend/qml/icons/img-welcome.png"
inkscape:export-xdpi="400" inkscape:export-xdpi="400"
inkscape:export-ydpi="400" inkscape:export-ydpi="400"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
@ -16,7 +16,7 @@
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"> xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview <sodipodi:namedview
id="namedview86" id="namedview112"
pagecolor="#505050" pagecolor="#505050"
bordercolor="#ffffff" bordercolor="#ffffff"
borderopacity="1" borderopacity="1"
@ -24,95 +24,159 @@
inkscape:pageopacity="0" inkscape:pageopacity="0"
inkscape:pagecheckerboard="1" inkscape:pagecheckerboard="1"
showgrid="false" showgrid="false"
inkscape:snap-global="true"
inkscape:snap-page="true" inkscape:snap-page="true"
inkscape:zoom="0.38460876" inkscape:zoom="0.69351284"
inkscape:cx="256.10441" inkscape:cx="93.004767"
inkscape:cy="252.20434" inkscape:cy="115.35475"
inkscape:window-width="1276" inkscape:window-width="1916"
inkscape:window-height="1401" inkscape:window-height="1041"
inkscape:window-x="0" inkscape:window-x="0"
inkscape:window-y="18" inkscape:window-y="18"
inkscape:window-maximized="1" inkscape:window-maximized="1"
inkscape:current-layer="svg84" /> inkscape:current-layer="svg110" />
<rect <rect
style="fill:#1c1b24;fill-opacity:1;stroke-width:4;stroke-linecap:round;stroke-linejoin:round" style="fill:#1c1b24;fill-opacity:1;stroke:none;stroke-width:27.9987;stroke-linecap:round;stroke-linejoin:round"
id="rect925" id="rect951"
width="265" width="265"
height="148" height="148"
x="0" x="0"
y="0" /> y="0"
ry="0"
inkscape:export-filename="/home/dev/gopath/src/github.com/ProtonMail/proton-bridge/internal/frontend/qml/icons/img-welcome.png"
inkscape:export-xdpi="400"
inkscape:export-ydpi="400" />
<path <path
d="M221.171 147H44.8555C43.1441 147 41.8047 145.661 41.8047 143.949V142.238C41.8047 140.526 43.1441 139.187 44.8555 139.187H221.171C222.882 139.187 224.221 140.526 224.221 142.238V143.949C224.221 145.661 222.808 147 221.171 147Z" d="M221.171 147.001H44.8555C43.1441 147.001 41.8047 145.661 41.8047 143.95V142.238C41.8047 140.527 43.1441 139.188 44.8555 139.188H221.171C222.882 139.188 224.221 140.527 224.221 142.238V143.95C224.221 145.661 222.808 147.001 221.171 147.001Z"
fill="#B0D4E5" fill="#B0D4E5"
id="path2" /> id="path2" />
<path <path
d="M141.83 143.503H123.376C120.995 143.503 119.135 141.568 119.135 139.261H146.072C146.072 141.568 144.211 143.503 141.83 143.503Z" d="M141.83 143.503H123.376C120.995 143.503 119.135 141.568 119.135 139.262H146.071C146.071 141.568 144.211 143.503 141.83 143.503Z"
fill="#DAF3FF" fill="#DAF3FF"
id="path4" /> id="path4" />
<path <path
d="M206.034 139.187H58.5011V53.9292C58.5011 49.0182 62.5193 45 67.4303 45H197.105C202.016 45 206.034 49.0182 206.034 53.9292V139.187Z" d="M206.034 139.187H58.501V53.9292C58.501 49.0182 62.5191 45 67.4302 45H197.104C202.016 45 206.034 49.0182 206.034 53.9292V139.187Z"
fill="url(#paint0_radial_470_16889)" fill="url(#paint0_radial_8674_44242)"
id="path6" /> id="path6" />
<path <path
d="M199.116 139.186H66.1674V55.3426C66.1674 54.152 67.1347 53.1847 68.3253 53.1847H196.883C198.074 53.1847 199.041 54.152 199.041 55.3426V139.186H199.116Z" d="M199.115 139.187H66.167V55.3434C66.167 54.1529 67.1343 53.1855 68.3249 53.1855H196.883C198.074 53.1855 199.041 54.1529 199.041 55.3434V139.187H199.115Z"
fill="url(#paint1_linear_470_16889)" fill="url(#paint1_linear_8674_44242)"
id="path8" /> id="path8" />
<path <path
d="M190.805 131.286H76.1797V62.518C76.1797 61.5228 77.028 60.7143 78.0721 60.7143H188.847C189.891 60.7143 190.739 61.5228 190.739 62.518V131.286H190.805Z" d="M190.805 131.286H76.1797V62.5185C76.1797 61.5234 77.028 60.7148 78.0721 60.7148H188.847C189.891 60.7148 190.739 61.5234 190.739 62.5185V131.286H190.805Z"
fill="url(#paint2_radial_470_16889)" fill="url(#paint2_radial_8674_44242)"
id="path10" /> id="path10" />
<path <path
d="M84.1558 70.7741C85.3064 70.7741 86.2392 69.8413 86.2392 68.6906C86.2392 67.5399 85.3064 66.6071 84.1558 66.6071C83.0051 66.6071 82.0723 67.5399 82.0723 68.6906C82.0723 69.8413 83.0051 70.7741 84.1558 70.7741Z" d="M84.1558 70.7744C85.3064 70.7744 86.2392 69.8416 86.2392 68.6909C86.2392 67.5402 85.3064 66.6074 84.1558 66.6074C83.0051 66.6074 82.0723 67.5402 82.0723 68.6909C82.0723 69.8416 83.0051 70.7744 84.1558 70.7744Z"
fill="#B0D4E5" fill="#B0D4E5"
id="path12" /> id="path12" />
<path <path
d="M90.6304 70.7741C91.781 70.7741 92.7139 69.8413 92.7139 68.6906C92.7139 67.5399 91.781 66.6071 90.6304 66.6071C89.4797 66.6071 88.5469 67.5399 88.5469 68.6906C88.5469 69.8413 89.4797 70.7741 90.6304 70.7741Z" d="M90.6304 70.7744C91.781 70.7744 92.7139 69.8416 92.7139 68.6909C92.7139 67.5402 91.781 66.6074 90.6304 66.6074C89.4797 66.6074 88.5469 67.5402 88.5469 68.6909C88.5469 69.8416 89.4797 70.7744 90.6304 70.7744Z"
fill="#B0D4E5" fill="#B0D4E5"
id="path14" /> id="path14" />
<path <path
d="M97.105 70.7741C98.2557 70.7741 99.1885 69.8413 99.1885 68.6906C99.1885 67.5399 98.2557 66.6071 97.105 66.6071C95.9543 66.6071 95.0215 67.5399 95.0215 68.6906C95.0215 69.8413 95.9543 70.7741 97.105 70.7741Z" d="M97.105 70.7744C98.2557 70.7744 99.1885 69.8416 99.1885 68.6909C99.1885 67.5402 98.2557 66.6074 97.105 66.6074C95.9543 66.6074 95.0215 67.5402 95.0215 68.6909C95.0215 69.8416 95.9543 70.7744 97.105 70.7744Z"
fill="#B0D4E5" fill="#B0D4E5"
id="path16" /> id="path16" />
<path <path
d="M242.633 76.3542H180.924C178.747 76.3542 177 74.562 177 72.3895V33.965C177 31.7926 178.774 30.0004 180.924 30.0004H242.606C244.783 30.0004 246.53 31.7926 246.53 33.965V72.3895C246.557 74.5891 244.783 76.3542 242.633 76.3542Z" d="M242.633 76.3538H180.924C178.747 76.3538 177 74.5616 177 72.3891V33.9646C177 31.7922 178.774 30 180.924 30H242.606C244.783 30 246.53 31.7922 246.53 33.9646V72.3891C246.557 74.5887 244.783 76.3538 242.633 76.3538Z"
fill="url(#paint3_linear_470_16889)" fill="url(#paint3_linear_8674_44242)"
id="path18" /> id="path18" />
<path <path
d="M209.232 56.69C210.689 57.8922 212.822 57.8922 214.279 56.69L245.431 31.042C244.729 30.4008 243.784 30.0001 242.758 30.0001H180.78C179.754 30.0001 178.809 30.4008 178.107 31.042L209.232 56.69Z" d="M209.232 56.6899C210.689 57.8921 212.822 57.8921 214.28 56.6899L245.431 31.0419C244.729 30.4007 243.784 30 242.758 30H180.78C179.754 30 178.809 30.4007 178.107 31.0419L209.232 56.6899Z"
fill="url(#paint4_linear_470_16889)" fill="url(#paint4_linear_8674_44242)"
id="path20" /> id="path20" />
<path <path
d="M160 81H104V89C109.523 89 114 93.4772 114 99V111H122V99C122 93.4772 126.477 89 132 89C137.523 89 142 93.4772 142 99V111H150V99C150 93.4772 154.477 89 160 89V81Z" d="M134.4 75C123.858 75 115.312 83.5451 115.312 94.0874V113.301C115.312 115.344 116.968 117 119.011 117H150.184C152.008 117 153.487 115.52 153.487 113.696V94.0874C153.487 83.5465 144.942 75 134.4 75ZM145.387 93.9814L137.044 101.01C135.538 102.279 133.336 102.279 131.83 101.01L123.487 93.9814C123.487 88.0172 128.323 83.1817 134.287 83.1817H134.587C140.551 83.1817 145.387 88.0172 145.387 93.9814Z"
fill="url(#paint5_linear_470_16889)" fill="#6D4AFF"
id="path22" /> id="path22" />
<path
d="M134.4 75C123.858 75 115.312 83.5451 115.312 94.0874V113.301C115.312 115.344 116.968 117 119.011 117H150.184C152.008 117 153.487 115.52 153.487 113.696V94.0874C153.487 83.5465 144.942 75 134.4 75ZM145.387 93.9814L137.044 101.01C135.538 102.279 133.336 102.279 131.83 101.01L123.487 93.9814C123.487 88.0172 128.323 83.1817 134.287 83.1817H134.587C140.551 83.1817 145.387 88.0172 145.387 93.9814Z"
fill="url(#paint5_linear_8674_44242)"
id="path24" />
<g
filter="url(#filter0_i_8674_44242)"
id="g28">
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M137.057 101.095C136.188 101.799 133.926 102.785 131.838 101.095C129.751 99.4048 125.418 95.6687 123.513 94.0119H123.524L123.487 93.9814C123.487 88.0172 128.323 83.1817 134.287 83.1817H134.587C140.551 83.1817 145.387 88.0172 145.387 93.9814L145.351 94.0119H145.383V117H150.184C152.008 117 153.487 115.52 153.487 113.696V94.0874C153.487 83.5465 144.942 75 134.4 75C123.858 75 115.312 83.5451 115.312 94.0874V95.2946L127.117 105.444C127.986 106.272 130.273 107.432 132.46 105.444C134.647 103.456 136.436 101.716 137.057 101.095Z"
fill="url(#paint6_radial_8674_44242)"
id="path26" />
</g>
<circle <circle
cx="239.278" cx="239.278"
cy="30.2778" cy="30.2778"
r="15.2778" r="15.2778"
fill="url(#paint6_linear_470_16889)" fill="url(#paint7_linear_8674_44242)"
id="circle24" /> id="circle30" />
<path <path
fill-rule="evenodd" fill-rule="evenodd"
clip-rule="evenodd" clip-rule="evenodd"
d="M245.702 26.6675C246.113 27.0761 246.116 27.7412 245.707 28.1529L238.128 35.7918C237.93 35.9905 237.662 36.1023 237.382 36.1023C237.102 36.1023 236.834 35.9905 236.636 35.7918L232.758 31.883C232.349 31.4713 232.352 30.8062 232.764 30.3976C233.175 29.989 233.84 29.9916 234.249 30.4034L237.382 33.5608L244.216 26.6733C244.625 26.2615 245.29 26.2589 245.702 26.6675Z" d="M245.702 26.668C246.113 27.0766 246.116 27.7417 245.707 28.1534L238.128 35.7923C237.93 35.9911 237.662 36.1028 237.382 36.1028C237.102 36.1028 236.834 35.9911 236.636 35.7923L232.758 31.8835C232.349 31.4718 232.352 30.8067 232.764 30.3981C233.175 29.9895 233.84 29.9921 234.249 30.4039L237.382 33.5613L244.216 26.6738C244.625 26.262 245.29 26.2595 245.702 26.668Z"
fill="white"
id="path26" />
<path
d="M0.878906 69.6212C0.878906 56.0233 11.9022 45 25.5001 45C39.0981 45 50.1214 56.0233 50.1214 69.6212V94.2425H25.5002C11.9022 94.2425 0.878906 83.2192 0.878906 69.6212Z"
fill="url(#paint7_linear_470_16889)"
id="path28" />
<path
d="M26.0002 55.0009C26.0002 55.0009 18.5507 54.7352 17.0005 63.2382V69.0397C17.0005 69.0397 17.0435 69.6597 18.766 70.944C20.4884 72.2283 24.8376 75.7712 26.0002 75.7712C27.1629 75.7712 31.5551 72.184 33.2345 70.944C34.9139 69.704 35 69.0397 35 69.0397V63.2382C33.4929 54.7352 26.0002 55.0009 26.0002 55.0009ZM20.919 66.4268V63.2825C21.5219 60.8467 23.5888 59.1196 26.0433 58.9867C28.4978 59.0753 30.5647 60.8467 31.1676 63.2825V66.4268H20.919Z"
fill="white"
id="path30" />
<path
d="M25.9998 77.0555C25.2677 76.9669 24.5788 76.7012 23.9328 76.3026C23.0286 75.6383 17 71.2097 17 71.2097V79.9784C17.0431 80.5984 17.5598 81.0412 18.1196 80.9969H33.8369C34.4397 81.0412 34.9565 80.5984 34.9995 80.0226V71.2097C34.9995 71.2097 28.971 75.6383 28.0667 76.3026C27.4638 76.7012 26.7749 76.9669 25.9998 77.0555Z"
fill="white" fill="white"
id="path32" /> id="path32" />
<path
d="M0.878906 69.6212C0.878906 56.0233 11.9022 45 25.5001 45V45C39.0981 45 50.1214 56.0233 50.1214 69.6212V94.2425H25.5002C11.9022 94.2425 0.878906 83.2192 0.878906 69.6212V69.6212Z"
fill="url(#paint8_linear_8674_44242)"
id="path34" />
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M31.4987 62.28V64.8004H33.9547C34.7948 64.8004 35.5056 65.4789 35.5056 66.3513V79.5019C35.5056 80.342 34.8271 81.0529 33.9547 81.0529H17.3791C16.539 81.0529 15.8281 80.3743 15.8281 79.5019V66.3513C15.8281 65.5112 16.5067 64.8004 17.3791 64.8004H19.802V62.28C19.802 59.0488 22.4192 56.4316 25.6504 56.4316C28.8815 56.4316 31.4987 59.0488 31.4987 62.28ZM29.0361 62.28V64.8004H22.3292V62.28C22.3292 59.9536 24.1059 58.9265 25.6827 58.9265C27.2594 58.9265 29.0361 59.9536 29.0361 62.28ZM25.9832 69.195C27.1141 69.195 28.0188 70.0997 28.0188 71.2306C28.0188 72.006 27.5988 72.6846 26.9526 73.0077L27.7927 76.6265H24.1738L25.0139 73.0077C24.3677 72.6523 23.9476 72.006 23.9476 71.2306C23.9476 70.0997 24.8523 69.195 25.9832 69.195Z"
fill="white"
id="path36" />
<defs <defs
id="defs82"> id="defs108">
<filter
id="filter0_i_8674_44242"
x="114.72"
y="75"
width="38.7675"
height="43.6537"
filterUnits="userSpaceOnUse"
color-interpolation-filters="sRGB">
<feFlood
flood-opacity="0"
result="BackgroundImageFix"
id="feFlood38" />
<feBlend
mode="normal"
in="SourceGraphic"
in2="BackgroundImageFix"
result="shape"
id="feBlend40" />
<feColorMatrix
in="SourceAlpha"
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
result="hardAlpha"
id="feColorMatrix42" />
<feOffset
dx="-0.592742"
dy="1.65375"
id="feOffset44" />
<feGaussianBlur
stdDeviation="4.44556"
id="feGaussianBlur46" />
<feComposite
in2="hardAlpha"
operator="arithmetic"
k2="-1"
k3="1"
id="feComposite48" />
<feColorMatrix
type="matrix"
values="0 0 0 0 0.462745 0 0 0 0 0.337255 0 0 0 0 1 0 0 0 0.24 0"
id="feColorMatrix50" />
<feBlend
mode="normal"
in2="shape"
result="effect1_innerShadow_8674_44242"
id="feBlend52" />
</filter>
<radialGradient <radialGradient
id="paint0_radial_470_16889" id="paint0_radial_8674_44242"
cx="0" cx="0"
cy="0" cy="0"
r="1" r="1"
@ -120,105 +184,121 @@
gradientTransform="translate(202 51.5) rotate(145.641) scale(59.357 92.9759)"> gradientTransform="translate(202 51.5) rotate(145.641) scale(59.357 92.9759)">
<stop <stop
stop-color="#292842" stop-color="#292842"
id="stop34" /> id="stop55" />
<stop <stop
offset="1" offset="1"
stop-color="#38385F" stop-color="#38385F"
id="stop36" /> id="stop57" />
</radialGradient> </radialGradient>
<linearGradient <linearGradient
id="paint1_linear_470_16889" id="paint1_linear_8674_44242"
x1="63.7082" x1="63.7079"
y1="144.987" y1="144.988"
x2="207.624" x2="207.623"
y2="58.7506" y2="58.7515"
gradientUnits="userSpaceOnUse"> gradientUnits="userSpaceOnUse">
<stop <stop
stop-color="#35168C" stop-color="#35168C"
id="stop39" /> id="stop60" />
<stop <stop
offset="0.317708" offset="0.317708"
stop-color="#FF5454" stop-color="#FF5454"
id="stop41" /> id="stop62" />
<stop <stop
offset="0.46875" offset="0.46875"
stop-color="#FFDD64" stop-color="#FFDD64"
id="stop43" /> id="stop64" />
<stop <stop
offset="0.677083" offset="0.677083"
stop-color="#BCE6FF" stop-color="#BCE6FF"
id="stop45" /> id="stop66" />
<stop <stop
offset="0.911458" offset="0.911458"
stop-color="#6983EF" stop-color="#6983EF"
id="stop47" /> id="stop68" />
<stop <stop
offset="1" offset="1"
stop-color="#2395FF" stop-color="#2395FF"
id="stop49" /> id="stop70" />
</linearGradient> </linearGradient>
<radialGradient <radialGradient
id="paint2_radial_470_16889" id="paint2_radial_8674_44242"
cx="0" cx="0"
cy="0" cy="0"
r="1" r="1"
gradientUnits="userSpaceOnUse" gradientUnits="userSpaceOnUse"
gradientTransform="translate(188.5 63.4994) rotate(135) scale(33.9411 55.1286)"> gradientTransform="translate(188.5 63.5) rotate(135) scale(33.9411 55.1286)">
<stop <stop
stop-color="#DDDBE3" stop-color="#DDDBE3"
id="stop52" /> id="stop73" />
<stop <stop
offset="1" offset="1"
stop-color="white" stop-color="white"
id="stop54" /> id="stop75" />
</radialGradient> </radialGradient>
<linearGradient <linearGradient
id="paint3_linear_470_16889" id="paint3_linear_8674_44242"
x1="211.765" x1="211.765"
y1="30.0004" y1="30"
x2="211.765" x2="211.765"
y2="66.4212" y2="66.4208"
gradientUnits="userSpaceOnUse"> gradientUnits="userSpaceOnUse">
<stop <stop
stop-color="#C1DEF8" stop-color="#C1DEF8"
id="stop57" /> id="stop78" />
<stop <stop
offset="1" offset="1"
stop-color="#ECFAFF" stop-color="#ECFAFF"
id="stop59" /> id="stop80" />
</linearGradient> </linearGradient>
<linearGradient <linearGradient
id="paint4_linear_470_16889" id="paint4_linear_8674_44242"
x1="211.769" x1="211.769"
y1="18.4116" y1="18.4116"
x2="211.769" x2="211.769"
y2="50.4178" y2="50.4177"
gradientUnits="userSpaceOnUse"> gradientUnits="userSpaceOnUse">
<stop <stop
stop-color="#DEEBF7" stop-color="#DEEBF7"
id="stop62" /> id="stop83" />
<stop <stop
offset="1" offset="1"
stop-color="white" stop-color="white"
id="stop64" /> id="stop85" />
</linearGradient> </linearGradient>
<linearGradient <linearGradient
id="paint5_linear_470_16889" id="paint5_linear_8674_44242"
x1="134.692" x1="116.679"
y1="70.9038" y1="121.846"
x2="139.324" x2="122.395"
y2="110.552" y2="105.692"
gradientUnits="userSpaceOnUse"> gradientUnits="userSpaceOnUse">
<stop <stop
stop-color="#ECAAFF" stop-color="#28B0E8"
id="stop67" /> id="stop88" />
<stop <stop
offset="1" offset="1"
stop-color="#6A48F6" stop-color="#C5B7FF"
id="stop69" /> stop-opacity="0"
id="stop90" />
</linearGradient> </linearGradient>
<radialGradient
id="paint6_radial_8674_44242"
cx="0"
cy="0"
r="1"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(151.237 120.479) rotate(-138.034) scale(48.3148 39.5031)">
<stop
stop-color="#E2DBFF"
id="stop93" />
<stop
offset="1"
stop-color="#6D4AFF"
id="stop95" />
</radialGradient>
<linearGradient <linearGradient
id="paint6_linear_470_16889" id="paint7_linear_8674_44242"
x1="240.861" x1="240.861"
y1="12.772" y1="12.772"
x2="241.004" x2="241.004"
@ -226,14 +306,14 @@
gradientUnits="userSpaceOnUse"> gradientUnits="userSpaceOnUse">
<stop <stop
stop-color="#2AF091" stop-color="#2AF091"
id="stop72" /> id="stop98" />
<stop <stop
offset="1" offset="1"
stop-color="#00C5A1" stop-color="#00C5A1"
id="stop74" /> id="stop100" />
</linearGradient> </linearGradient>
<linearGradient <linearGradient
id="paint7_linear_470_16889" id="paint8_linear_8674_44242"
x1="41.1252" x1="41.1252"
y1="56.3637" y1="56.3637"
x2="5.14027" x2="5.14027"
@ -241,11 +321,11 @@
gradientUnits="userSpaceOnUse"> gradientUnits="userSpaceOnUse">
<stop <stop
stop-color="#FFD66C" stop-color="#FFD66C"
id="stop77" /> id="stop103" />
<stop <stop
offset="1" offset="1"
stop-color="#FF8E4F" stop-color="#FF8E4F"
id="stop79" /> id="stop105" />
</linearGradient> </linearGradient>
</defs> </defs>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 9.0 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 63 KiB

After

Width:  |  Height:  |  Size: 73 KiB

View File

@ -5,10 +5,10 @@
viewBox="0 0 265 148" viewBox="0 0 265 148"
fill="none" fill="none"
version="1.1" version="1.1"
id="svg84" id="svg110"
sodipodi:docname="img-welcome.svg" sodipodi:docname="img-welcome.svg"
inkscape:version="1.1.2 (0a00cf5339, 2022-02-04, custom)" inkscape:version="1.1.2 (0a00cf5339, 2022-02-04, custom)"
inkscape:export-filename="/home/dev/gopath/src/github.com/ProtonMail/proton-bridge/v2/internal/frontend/qml/icons/img-welcome.png" inkscape:export-filename="/home/dev/gopath/src/github.com/ProtonMail/proton-bridge/internal/frontend/qml/icons/img-welcome.png"
inkscape:export-xdpi="400" inkscape:export-xdpi="400"
inkscape:export-ydpi="400" inkscape:export-ydpi="400"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
@ -16,7 +16,7 @@
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"> xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview <sodipodi:namedview
id="namedview86" id="namedview112"
pagecolor="#505050" pagecolor="#505050"
bordercolor="#ffffff" bordercolor="#ffffff"
borderopacity="1" borderopacity="1"
@ -24,95 +24,159 @@
inkscape:pageopacity="0" inkscape:pageopacity="0"
inkscape:pagecheckerboard="1" inkscape:pagecheckerboard="1"
showgrid="false" showgrid="false"
inkscape:snap-global="true"
inkscape:snap-page="true" inkscape:snap-page="true"
inkscape:zoom="0.38460876" inkscape:zoom="0.69351284"
inkscape:cx="256.10441" inkscape:cx="93.004767"
inkscape:cy="252.20434" inkscape:cy="115.35475"
inkscape:window-width="1276" inkscape:window-width="1916"
inkscape:window-height="1401" inkscape:window-height="1041"
inkscape:window-x="1280" inkscape:window-x="0"
inkscape:window-y="18" inkscape:window-y="18"
inkscape:window-maximized="1" inkscape:window-maximized="1"
inkscape:current-layer="svg84" /> inkscape:current-layer="svg110" />
<rect <rect
style="fill:#ffffff;fill-opacity:1;stroke-width:4;stroke-linecap:round;stroke-linejoin:round" style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:27.9987;stroke-linecap:round;stroke-linejoin:round"
id="rect925" id="rect951"
width="265" width="265"
height="148" height="148"
x="0" x="0"
y="0" /> y="0"
ry="0"
inkscape:export-filename="/home/dev/gopath/src/github.com/ProtonMail/proton-bridge/internal/frontend/qml/icons/img-welcome.png"
inkscape:export-xdpi="400"
inkscape:export-ydpi="400" />
<path <path
d="M221.171 147H44.8555C43.1441 147 41.8047 145.661 41.8047 143.949V142.238C41.8047 140.526 43.1441 139.187 44.8555 139.187H221.171C222.882 139.187 224.221 140.526 224.221 142.238V143.949C224.221 145.661 222.808 147 221.171 147Z" d="M221.171 147.001H44.8555C43.1441 147.001 41.8047 145.661 41.8047 143.95V142.238C41.8047 140.527 43.1441 139.188 44.8555 139.188H221.171C222.882 139.188 224.221 140.527 224.221 142.238V143.95C224.221 145.661 222.808 147.001 221.171 147.001Z"
fill="#B0D4E5" fill="#B0D4E5"
id="path2" /> id="path2" />
<path <path
d="M141.83 143.503H123.376C120.995 143.503 119.135 141.568 119.135 139.261H146.072C146.072 141.568 144.211 143.503 141.83 143.503Z" d="M141.83 143.503H123.376C120.995 143.503 119.135 141.568 119.135 139.262H146.071C146.071 141.568 144.211 143.503 141.83 143.503Z"
fill="#DAF3FF" fill="#DAF3FF"
id="path4" /> id="path4" />
<path <path
d="M206.034 139.187H58.5011V53.9292C58.5011 49.0182 62.5193 45 67.4303 45H197.105C202.016 45 206.034 49.0182 206.034 53.9292V139.187Z" d="M206.034 139.187H58.501V53.9292C58.501 49.0182 62.5191 45 67.4302 45H197.104C202.016 45 206.034 49.0182 206.034 53.9292V139.187Z"
fill="url(#paint0_radial_470_16889)" fill="url(#paint0_radial_8674_44242)"
id="path6" /> id="path6" />
<path <path
d="M199.116 139.186H66.1674V55.3426C66.1674 54.152 67.1347 53.1847 68.3253 53.1847H196.883C198.074 53.1847 199.041 54.152 199.041 55.3426V139.186H199.116Z" d="M199.115 139.187H66.167V55.3434C66.167 54.1529 67.1343 53.1855 68.3249 53.1855H196.883C198.074 53.1855 199.041 54.1529 199.041 55.3434V139.187H199.115Z"
fill="url(#paint1_linear_470_16889)" fill="url(#paint1_linear_8674_44242)"
id="path8" /> id="path8" />
<path <path
d="M190.805 131.286H76.1797V62.518C76.1797 61.5228 77.028 60.7143 78.0721 60.7143H188.847C189.891 60.7143 190.739 61.5228 190.739 62.518V131.286H190.805Z" d="M190.805 131.286H76.1797V62.5185C76.1797 61.5234 77.028 60.7148 78.0721 60.7148H188.847C189.891 60.7148 190.739 61.5234 190.739 62.5185V131.286H190.805Z"
fill="url(#paint2_radial_470_16889)" fill="url(#paint2_radial_8674_44242)"
id="path10" /> id="path10" />
<path <path
d="M84.1558 70.7741C85.3064 70.7741 86.2392 69.8413 86.2392 68.6906C86.2392 67.5399 85.3064 66.6071 84.1558 66.6071C83.0051 66.6071 82.0723 67.5399 82.0723 68.6906C82.0723 69.8413 83.0051 70.7741 84.1558 70.7741Z" d="M84.1558 70.7744C85.3064 70.7744 86.2392 69.8416 86.2392 68.6909C86.2392 67.5402 85.3064 66.6074 84.1558 66.6074C83.0051 66.6074 82.0723 67.5402 82.0723 68.6909C82.0723 69.8416 83.0051 70.7744 84.1558 70.7744Z"
fill="#B0D4E5" fill="#B0D4E5"
id="path12" /> id="path12" />
<path <path
d="M90.6304 70.7741C91.781 70.7741 92.7139 69.8413 92.7139 68.6906C92.7139 67.5399 91.781 66.6071 90.6304 66.6071C89.4797 66.6071 88.5469 67.5399 88.5469 68.6906C88.5469 69.8413 89.4797 70.7741 90.6304 70.7741Z" d="M90.6304 70.7744C91.781 70.7744 92.7139 69.8416 92.7139 68.6909C92.7139 67.5402 91.781 66.6074 90.6304 66.6074C89.4797 66.6074 88.5469 67.5402 88.5469 68.6909C88.5469 69.8416 89.4797 70.7744 90.6304 70.7744Z"
fill="#B0D4E5" fill="#B0D4E5"
id="path14" /> id="path14" />
<path <path
d="M97.105 70.7741C98.2557 70.7741 99.1885 69.8413 99.1885 68.6906C99.1885 67.5399 98.2557 66.6071 97.105 66.6071C95.9543 66.6071 95.0215 67.5399 95.0215 68.6906C95.0215 69.8413 95.9543 70.7741 97.105 70.7741Z" d="M97.105 70.7744C98.2557 70.7744 99.1885 69.8416 99.1885 68.6909C99.1885 67.5402 98.2557 66.6074 97.105 66.6074C95.9543 66.6074 95.0215 67.5402 95.0215 68.6909C95.0215 69.8416 95.9543 70.7744 97.105 70.7744Z"
fill="#B0D4E5" fill="#B0D4E5"
id="path16" /> id="path16" />
<path <path
d="M242.633 76.3542H180.924C178.747 76.3542 177 74.562 177 72.3895V33.965C177 31.7926 178.774 30.0004 180.924 30.0004H242.606C244.783 30.0004 246.53 31.7926 246.53 33.965V72.3895C246.557 74.5891 244.783 76.3542 242.633 76.3542Z" d="M242.633 76.3538H180.924C178.747 76.3538 177 74.5616 177 72.3891V33.9646C177 31.7922 178.774 30 180.924 30H242.606C244.783 30 246.53 31.7922 246.53 33.9646V72.3891C246.557 74.5887 244.783 76.3538 242.633 76.3538Z"
fill="url(#paint3_linear_470_16889)" fill="url(#paint3_linear_8674_44242)"
id="path18" /> id="path18" />
<path <path
d="M209.232 56.69C210.689 57.8922 212.822 57.8922 214.279 56.69L245.431 31.042C244.729 30.4008 243.784 30.0001 242.758 30.0001H180.78C179.754 30.0001 178.809 30.4008 178.107 31.042L209.232 56.69Z" d="M209.232 56.6899C210.689 57.8921 212.822 57.8921 214.28 56.6899L245.431 31.0419C244.729 30.4007 243.784 30 242.758 30H180.78C179.754 30 178.809 30.4007 178.107 31.0419L209.232 56.6899Z"
fill="url(#paint4_linear_470_16889)" fill="url(#paint4_linear_8674_44242)"
id="path20" /> id="path20" />
<path <path
d="M160 81H104V89C109.523 89 114 93.4772 114 99V111H122V99C122 93.4772 126.477 89 132 89C137.523 89 142 93.4772 142 99V111H150V99C150 93.4772 154.477 89 160 89V81Z" d="M134.4 75C123.858 75 115.312 83.5451 115.312 94.0874V113.301C115.312 115.344 116.968 117 119.011 117H150.184C152.008 117 153.487 115.52 153.487 113.696V94.0874C153.487 83.5465 144.942 75 134.4 75ZM145.387 93.9814L137.044 101.01C135.538 102.279 133.336 102.279 131.83 101.01L123.487 93.9814C123.487 88.0172 128.323 83.1817 134.287 83.1817H134.587C140.551 83.1817 145.387 88.0172 145.387 93.9814Z"
fill="url(#paint5_linear_470_16889)" fill="#6D4AFF"
id="path22" /> id="path22" />
<path
d="M134.4 75C123.858 75 115.312 83.5451 115.312 94.0874V113.301C115.312 115.344 116.968 117 119.011 117H150.184C152.008 117 153.487 115.52 153.487 113.696V94.0874C153.487 83.5465 144.942 75 134.4 75ZM145.387 93.9814L137.044 101.01C135.538 102.279 133.336 102.279 131.83 101.01L123.487 93.9814C123.487 88.0172 128.323 83.1817 134.287 83.1817H134.587C140.551 83.1817 145.387 88.0172 145.387 93.9814Z"
fill="url(#paint5_linear_8674_44242)"
id="path24" />
<g
filter="url(#filter0_i_8674_44242)"
id="g28">
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M137.057 101.095C136.188 101.799 133.926 102.785 131.838 101.095C129.751 99.4048 125.418 95.6687 123.513 94.0119H123.524L123.487 93.9814C123.487 88.0172 128.323 83.1817 134.287 83.1817H134.587C140.551 83.1817 145.387 88.0172 145.387 93.9814L145.351 94.0119H145.383V117H150.184C152.008 117 153.487 115.52 153.487 113.696V94.0874C153.487 83.5465 144.942 75 134.4 75C123.858 75 115.312 83.5451 115.312 94.0874V95.2946L127.117 105.444C127.986 106.272 130.273 107.432 132.46 105.444C134.647 103.456 136.436 101.716 137.057 101.095Z"
fill="url(#paint6_radial_8674_44242)"
id="path26" />
</g>
<circle <circle
cx="239.278" cx="239.278"
cy="30.2778" cy="30.2778"
r="15.2778" r="15.2778"
fill="url(#paint6_linear_470_16889)" fill="url(#paint7_linear_8674_44242)"
id="circle24" /> id="circle30" />
<path <path
fill-rule="evenodd" fill-rule="evenodd"
clip-rule="evenodd" clip-rule="evenodd"
d="M245.702 26.6675C246.113 27.0761 246.116 27.7412 245.707 28.1529L238.128 35.7918C237.93 35.9905 237.662 36.1023 237.382 36.1023C237.102 36.1023 236.834 35.9905 236.636 35.7918L232.758 31.883C232.349 31.4713 232.352 30.8062 232.764 30.3976C233.175 29.989 233.84 29.9916 234.249 30.4034L237.382 33.5608L244.216 26.6733C244.625 26.2615 245.29 26.2589 245.702 26.6675Z" d="M245.702 26.668C246.113 27.0766 246.116 27.7417 245.707 28.1534L238.128 35.7923C237.93 35.9911 237.662 36.1028 237.382 36.1028C237.102 36.1028 236.834 35.9911 236.636 35.7923L232.758 31.8835C232.349 31.4718 232.352 30.8067 232.764 30.3981C233.175 29.9895 233.84 29.9921 234.249 30.4039L237.382 33.5613L244.216 26.6738C244.625 26.262 245.29 26.2595 245.702 26.668Z"
fill="white"
id="path26" />
<path
d="M0.878906 69.6212C0.878906 56.0233 11.9022 45 25.5001 45C39.0981 45 50.1214 56.0233 50.1214 69.6212V94.2425H25.5002C11.9022 94.2425 0.878906 83.2192 0.878906 69.6212Z"
fill="url(#paint7_linear_470_16889)"
id="path28" />
<path
d="M26.0002 55.0009C26.0002 55.0009 18.5507 54.7352 17.0005 63.2382V69.0397C17.0005 69.0397 17.0435 69.6597 18.766 70.944C20.4884 72.2283 24.8376 75.7712 26.0002 75.7712C27.1629 75.7712 31.5551 72.184 33.2345 70.944C34.9139 69.704 35 69.0397 35 69.0397V63.2382C33.4929 54.7352 26.0002 55.0009 26.0002 55.0009ZM20.919 66.4268V63.2825C21.5219 60.8467 23.5888 59.1196 26.0433 58.9867C28.4978 59.0753 30.5647 60.8467 31.1676 63.2825V66.4268H20.919Z"
fill="white"
id="path30" />
<path
d="M25.9998 77.0555C25.2677 76.9669 24.5788 76.7012 23.9328 76.3026C23.0286 75.6383 17 71.2097 17 71.2097V79.9784C17.0431 80.5984 17.5598 81.0412 18.1196 80.9969H33.8369C34.4397 81.0412 34.9565 80.5984 34.9995 80.0226V71.2097C34.9995 71.2097 28.971 75.6383 28.0667 76.3026C27.4638 76.7012 26.7749 76.9669 25.9998 77.0555Z"
fill="white" fill="white"
id="path32" /> id="path32" />
<path
d="M0.878906 69.6212C0.878906 56.0233 11.9022 45 25.5001 45V45C39.0981 45 50.1214 56.0233 50.1214 69.6212V94.2425H25.5002C11.9022 94.2425 0.878906 83.2192 0.878906 69.6212V69.6212Z"
fill="url(#paint8_linear_8674_44242)"
id="path34" />
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M31.4987 62.28V64.8004H33.9547C34.7948 64.8004 35.5056 65.4789 35.5056 66.3513V79.5019C35.5056 80.342 34.8271 81.0529 33.9547 81.0529H17.3791C16.539 81.0529 15.8281 80.3743 15.8281 79.5019V66.3513C15.8281 65.5112 16.5067 64.8004 17.3791 64.8004H19.802V62.28C19.802 59.0488 22.4192 56.4316 25.6504 56.4316C28.8815 56.4316 31.4987 59.0488 31.4987 62.28ZM29.0361 62.28V64.8004H22.3292V62.28C22.3292 59.9536 24.1059 58.9265 25.6827 58.9265C27.2594 58.9265 29.0361 59.9536 29.0361 62.28ZM25.9832 69.195C27.1141 69.195 28.0188 70.0997 28.0188 71.2306C28.0188 72.006 27.5988 72.6846 26.9526 73.0077L27.7927 76.6265H24.1738L25.0139 73.0077C24.3677 72.6523 23.9476 72.006 23.9476 71.2306C23.9476 70.0997 24.8523 69.195 25.9832 69.195Z"
fill="white"
id="path36" />
<defs <defs
id="defs82"> id="defs108">
<filter
id="filter0_i_8674_44242"
x="114.72"
y="75"
width="38.7675"
height="43.6537"
filterUnits="userSpaceOnUse"
color-interpolation-filters="sRGB">
<feFlood
flood-opacity="0"
result="BackgroundImageFix"
id="feFlood38" />
<feBlend
mode="normal"
in="SourceGraphic"
in2="BackgroundImageFix"
result="shape"
id="feBlend40" />
<feColorMatrix
in="SourceAlpha"
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
result="hardAlpha"
id="feColorMatrix42" />
<feOffset
dx="-0.592742"
dy="1.65375"
id="feOffset44" />
<feGaussianBlur
stdDeviation="4.44556"
id="feGaussianBlur46" />
<feComposite
in2="hardAlpha"
operator="arithmetic"
k2="-1"
k3="1"
id="feComposite48" />
<feColorMatrix
type="matrix"
values="0 0 0 0 0.462745 0 0 0 0 0.337255 0 0 0 0 1 0 0 0 0.24 0"
id="feColorMatrix50" />
<feBlend
mode="normal"
in2="shape"
result="effect1_innerShadow_8674_44242"
id="feBlend52" />
</filter>
<radialGradient <radialGradient
id="paint0_radial_470_16889" id="paint0_radial_8674_44242"
cx="0" cx="0"
cy="0" cy="0"
r="1" r="1"
@ -120,105 +184,121 @@
gradientTransform="translate(202 51.5) rotate(145.641) scale(59.357 92.9759)"> gradientTransform="translate(202 51.5) rotate(145.641) scale(59.357 92.9759)">
<stop <stop
stop-color="#292842" stop-color="#292842"
id="stop34" /> id="stop55" />
<stop <stop
offset="1" offset="1"
stop-color="#38385F" stop-color="#38385F"
id="stop36" /> id="stop57" />
</radialGradient> </radialGradient>
<linearGradient <linearGradient
id="paint1_linear_470_16889" id="paint1_linear_8674_44242"
x1="63.7082" x1="63.7079"
y1="144.987" y1="144.988"
x2="207.624" x2="207.623"
y2="58.7506" y2="58.7515"
gradientUnits="userSpaceOnUse"> gradientUnits="userSpaceOnUse">
<stop <stop
stop-color="#35168C" stop-color="#35168C"
id="stop39" /> id="stop60" />
<stop <stop
offset="0.317708" offset="0.317708"
stop-color="#FF5454" stop-color="#FF5454"
id="stop41" /> id="stop62" />
<stop <stop
offset="0.46875" offset="0.46875"
stop-color="#FFDD64" stop-color="#FFDD64"
id="stop43" /> id="stop64" />
<stop <stop
offset="0.677083" offset="0.677083"
stop-color="#BCE6FF" stop-color="#BCE6FF"
id="stop45" /> id="stop66" />
<stop <stop
offset="0.911458" offset="0.911458"
stop-color="#6983EF" stop-color="#6983EF"
id="stop47" /> id="stop68" />
<stop <stop
offset="1" offset="1"
stop-color="#2395FF" stop-color="#2395FF"
id="stop49" /> id="stop70" />
</linearGradient> </linearGradient>
<radialGradient <radialGradient
id="paint2_radial_470_16889" id="paint2_radial_8674_44242"
cx="0" cx="0"
cy="0" cy="0"
r="1" r="1"
gradientUnits="userSpaceOnUse" gradientUnits="userSpaceOnUse"
gradientTransform="translate(188.5 63.4994) rotate(135) scale(33.9411 55.1286)"> gradientTransform="translate(188.5 63.5) rotate(135) scale(33.9411 55.1286)">
<stop <stop
stop-color="#DDDBE3" stop-color="#DDDBE3"
id="stop52" /> id="stop73" />
<stop <stop
offset="1" offset="1"
stop-color="white" stop-color="white"
id="stop54" /> id="stop75" />
</radialGradient> </radialGradient>
<linearGradient <linearGradient
id="paint3_linear_470_16889" id="paint3_linear_8674_44242"
x1="211.765" x1="211.765"
y1="30.0004" y1="30"
x2="211.765" x2="211.765"
y2="66.4212" y2="66.4208"
gradientUnits="userSpaceOnUse"> gradientUnits="userSpaceOnUse">
<stop <stop
stop-color="#C1DEF8" stop-color="#C1DEF8"
id="stop57" /> id="stop78" />
<stop <stop
offset="1" offset="1"
stop-color="#ECFAFF" stop-color="#ECFAFF"
id="stop59" /> id="stop80" />
</linearGradient> </linearGradient>
<linearGradient <linearGradient
id="paint4_linear_470_16889" id="paint4_linear_8674_44242"
x1="211.769" x1="211.769"
y1="18.4116" y1="18.4116"
x2="211.769" x2="211.769"
y2="50.4178" y2="50.4177"
gradientUnits="userSpaceOnUse"> gradientUnits="userSpaceOnUse">
<stop <stop
stop-color="#DEEBF7" stop-color="#DEEBF7"
id="stop62" /> id="stop83" />
<stop <stop
offset="1" offset="1"
stop-color="white" stop-color="white"
id="stop64" /> id="stop85" />
</linearGradient> </linearGradient>
<linearGradient <linearGradient
id="paint5_linear_470_16889" id="paint5_linear_8674_44242"
x1="134.692" x1="116.679"
y1="70.9038" y1="121.846"
x2="139.324" x2="122.395"
y2="110.552" y2="105.692"
gradientUnits="userSpaceOnUse"> gradientUnits="userSpaceOnUse">
<stop <stop
stop-color="#ECAAFF" stop-color="#28B0E8"
id="stop67" /> id="stop88" />
<stop <stop
offset="1" offset="1"
stop-color="#6A48F6" stop-color="#C5B7FF"
id="stop69" /> stop-opacity="0"
id="stop90" />
</linearGradient> </linearGradient>
<radialGradient
id="paint6_radial_8674_44242"
cx="0"
cy="0"
r="1"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(151.237 120.479) rotate(-138.034) scale(48.3148 39.5031)">
<stop
stop-color="#E2DBFF"
id="stop93" />
<stop
offset="1"
stop-color="#6D4AFF"
id="stop95" />
</radialGradient>
<linearGradient <linearGradient
id="paint6_linear_470_16889" id="paint7_linear_8674_44242"
x1="240.861" x1="240.861"
y1="12.772" y1="12.772"
x2="241.004" x2="241.004"
@ -226,14 +306,14 @@
gradientUnits="userSpaceOnUse"> gradientUnits="userSpaceOnUse">
<stop <stop
stop-color="#2AF091" stop-color="#2AF091"
id="stop72" /> id="stop98" />
<stop <stop
offset="1" offset="1"
stop-color="#00C5A1" stop-color="#00C5A1"
id="stop74" /> id="stop100" />
</linearGradient> </linearGradient>
<linearGradient <linearGradient
id="paint7_linear_470_16889" id="paint8_linear_8674_44242"
x1="41.1252" x1="41.1252"
y1="56.3637" y1="56.3637"
x2="5.14027" x2="5.14027"
@ -241,11 +321,11 @@
gradientUnits="userSpaceOnUse"> gradientUnits="userSpaceOnUse">
<stop <stop
stop-color="#FFD66C" stop-color="#FFD66C"
id="stop77" /> id="stop103" />
<stop <stop
offset="1" offset="1"
stop-color="#FF8E4F" stop-color="#FF8E4F"
id="stop79" /> id="stop105" />
</linearGradient> </linearGradient>
</defs> </defs>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 9.0 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 119 KiB

After

Width:  |  Height:  |  Size: 110 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 132 KiB

After

Width:  |  Height:  |  Size: 123 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 130 KiB

After

Width:  |  Height:  |  Size: 122 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 127 KiB

After

Width:  |  Height:  |  Size: 119 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 25 KiB

View File

@ -9,7 +9,7 @@
id="svg5" id="svg5"
inkscape:version="1.1.2 (0a00cf5339, 2022-02-04, custom)" inkscape:version="1.1.2 (0a00cf5339, 2022-02-04, custom)"
sodipodi:docname="systray.svg" sodipodi:docname="systray.svg"
inkscape:export-filename="/home/cuto/Downloads/systray/systray-color-update.png" inkscape:export-filename="/tmp/bridge/internal/frontend/qml/icons/systray-color-update.png"
inkscape:export-xdpi="192.00002" inkscape:export-xdpi="192.00002"
inkscape:export-ydpi="192.00002" inkscape:export-ydpi="192.00002"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
@ -24,19 +24,22 @@
inkscape:pageshadow="0" inkscape:pageshadow="0"
inkscape:pageopacity="0" inkscape:pageopacity="0"
inkscape:pagecheckerboard="1" inkscape:pagecheckerboard="1"
inkscape:document-units="mm" inkscape:document-units="px"
showgrid="false" showgrid="false"
inkscape:zoom="1.7021484" inkscape:zoom="0.8510742"
inkscape:cx="191.81641" inkscape:cx="300.20884"
inkscape:cy="297.85886" inkscape:cy="445.31957"
inkscape:window-width="2556" inkscape:window-width="1372"
inkscape:window-height="1401" inkscape:window-height="1401"
inkscape:window-x="0" inkscape:window-x="1184"
inkscape:window-y="18" inkscape:window-y="18"
inkscape:window-maximized="1" inkscape:window-maximized="1"
inkscape:current-layer="layer6" inkscape:current-layer="layer2"
units="px" units="px"
width="512px" /> width="512px"
showguides="true"
inkscape:guide-bbox="true"
inkscape:snap-global="false" />
<defs <defs
id="defs2"> id="defs2">
<filter <filter
@ -309,15 +312,14 @@
</linearGradient> </linearGradient>
</defs> </defs>
<g <g
inkscape:label="m-n" inkscape:label="systray-mono-norm"
inkscape:groupmode="layer" inkscape:groupmode="layer"
id="layer1" id="layer1"
style="display:none" style="display:none">
sodipodi:insensitive="true">
<g <g
style="fill:#000000" style="fill:#000000"
id="g955" id="g955"
transform="matrix(7.4083333,0,0,7.4083333,8.4666669,12.170834)"> transform="matrix(7.0910539,0,0,7.0910539,11.123103,14.495302)">
<path <path
d="M 8,0 C 4.13377,0 1,3.05181 1,6.81693 V 13.6791 C 1,14.4086 1.60727,15 2.35639,15 H 13.7885 C 14.4573,15 15,14.4715 15,13.8202 V 6.81693 C 15,3.05231 11.8662,0 8,0 Z m 4.8462,6.24336 -3.87649,3.0458 c -0.55224,0.45324 -1.35992,0.45324 -1.91216,0 l -3.9037,-3.0458 c 0,-2.13007 2.07902,-4.1005 4.80476,-4.1005 h 0.11004 c 2.72575,0 4.77755,1.97043 4.77755,4.1005 z" d="M 8,0 C 4.13377,0 1,3.05181 1,6.81693 V 13.6791 C 1,14.4086 1.60727,15 2.35639,15 H 13.7885 C 14.4573,15 15,14.4715 15,13.8202 V 6.81693 C 15,3.05231 11.8662,0 8,0 Z m 4.8462,6.24336 -3.87649,3.0458 c -0.55224,0.45324 -1.35992,0.45324 -1.91216,0 l -3.9037,-3.0458 c 0,-2.13007 2.07902,-4.1005 4.80476,-4.1005 h 0.11004 c 2.72575,0 4.77755,1.97043 4.77755,4.1005 z"
fill="#000000" fill="#000000"
@ -328,13 +330,13 @@
<g <g
inkscape:groupmode="layer" inkscape:groupmode="layer"
id="layer2" id="layer2"
inkscape:label="m-w" inkscape:label="systray-mono-warn"
style="display:none" style="display:none"
sodipodi:insensitive="true"> sodipodi:insensitive="true">
<g <g
style="fill:none" style="fill:none"
id="g1073" id="g1073"
transform="matrix(7.4083333,0,0,7.4083333,8.4666669,4.7659826)"> transform="matrix(7.0910539,0,0,7.0910539,11.123103,7.4075805)">
<g <g
id="g1062"> id="g1062">
<path <path
@ -355,13 +357,13 @@
<g <g
inkscape:groupmode="layer" inkscape:groupmode="layer"
id="layer3" id="layer3"
inkscape:label="m-e" inkscape:label="systray-mono-error"
style="display:none" style="display:none"
sodipodi:insensitive="true"> sodipodi:insensitive="true">
<g <g
style="fill:none" style="fill:none"
id="g1123" id="g1123"
transform="matrix(7.4083333,0,0,7.4083333,8.4666669,12.170834)"> transform="matrix(7.0910539,0,0,7.0910539,11.123103,14.495302)">
<g <g
id="g1112"> id="g1112">
<path <path
@ -383,13 +385,13 @@
<g <g
inkscape:groupmode="layer" inkscape:groupmode="layer"
id="layer4" id="layer4"
inkscape:label="m-u" inkscape:label="systray-mono-update"
style="display:none" style="display:none"
sodipodi:insensitive="true"> sodipodi:insensitive="true">
<g <g
style="fill:none" style="fill:none"
id="g1201" id="g1201"
transform="matrix(7.4083333,0,0,7.4083333,8.4666669,12.170834)"> transform="matrix(7.0910539,0,0,7.0910539,11.123103,14.495302)">
<g <g
id="g1190"> id="g1190">
<path <path
@ -410,13 +412,13 @@
<g <g
inkscape:groupmode="layer" inkscape:groupmode="layer"
id="layer5" id="layer5"
inkscape:label="c-n" inkscape:label="systray-color-norm"
style="display:none;opacity:1" style="display:none;opacity:1"
sodipodi:insensitive="true"> sodipodi:insensitive="true">
<g <g
style="fill:none" style="fill:none"
id="g1337" id="g1337"
transform="matrix(7.4223337,0,0,7.4223337,8.220297,12.170834)"> transform="matrix(7.1044547,0,0,7.1044547,10.887285,14.495302)">
<path <path
d="M 8,0 C 4.13377,0 1,3.05181 1,6.81693 V 13.6791 C 1,14.4086 1.60727,15 2.35639,15 H 13.7885 C 14.4573,15 15,14.4715 15,13.8202 V 6.81693 C 15,3.05231 11.8662,0 8,0 Z m 4.0293,6.77908 -3.05959,2.51008 c -0.55224,0.45324 -1.35992,0.45324 -1.91216,0 L 3.99798,6.77908 c 0,-2.13008 1.77335,-3.85705 3.96063,-3.85705 h 0.11004 c 2.18725,0 3.96065,1.72697 3.96065,3.85705 z" d="M 8,0 C 4.13377,0 1,3.05181 1,6.81693 V 13.6791 C 1,14.4086 1.60727,15 2.35639,15 H 13.7885 C 14.4573,15 15,14.4715 15,13.8202 V 6.81693 C 15,3.05231 11.8662,0 8,0 Z m 4.0293,6.77908 -3.05959,2.51008 c -0.55224,0.45324 -1.35992,0.45324 -1.91216,0 L 3.99798,6.77908 c 0,-2.13008 1.77335,-3.85705 3.96063,-3.85705 h 0.11004 c 2.18725,0 3.96065,1.72697 3.96065,3.85705 z"
fill="#6d4aff" fill="#6d4aff"
@ -442,13 +444,13 @@
<g <g
inkscape:groupmode="layer" inkscape:groupmode="layer"
id="layer6" id="layer6"
inkscape:label="c-w" inkscape:label="systray-color-warn"
style="display:none;opacity:1" style="display:none;opacity:1"
sodipodi:insensitive="true"> sodipodi:insensitive="true">
<g <g
style="fill:none" style="fill:none"
id="g1752" id="g1752"
transform="matrix(7.4040336,0,0,7.4040336,8.3915095,12.37535)"> transform="matrix(7.0869383,0,0,7.0869383,11.051165,14.691059)">
<path <path
fill-rule="evenodd" fill-rule="evenodd"
clip-rule="evenodd" clip-rule="evenodd"
@ -484,13 +486,13 @@
<g <g
inkscape:groupmode="layer" inkscape:groupmode="layer"
id="layer7" id="layer7"
inkscape:label="c-e" inkscape:label="systray-color-error"
style="display:none" style="display:none"
sodipodi:insensitive="true"> sodipodi:insensitive="true">
<g <g
style="fill:none" style="fill:none"
id="g1888" id="g1888"
transform="matrix(7.4083333,0,0,7.4083333,8.3477474,12.346202)"> transform="matrix(7.0910539,0,0,7.0910539,11.009277,14.663159)">
<path <path
fill-rule="evenodd" fill-rule="evenodd"
clip-rule="evenodd" clip-rule="evenodd"
@ -516,12 +518,12 @@
<g <g
inkscape:groupmode="layer" inkscape:groupmode="layer"
id="layer8" id="layer8"
inkscape:label="c-u" inkscape:label="systray-color-update"
style="display:inline;opacity:1" style="display:inline;opacity:1"
sodipodi:insensitive="true"> sodipodi:insensitive="true">
<g <g
id="g2144" id="g2144"
transform="matrix(0.99765808,0,0,0.99765808,0.35589462,0.38736438)"> transform="matrix(0.95493101,0,0,0.95493101,3.3596943,3.216487)">
<g <g
id="g2135"> id="g2135">
<g <g

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

View File

@ -155,6 +155,9 @@ type QMLBackend struct {
_ func() `signal:apiCertIssue` _ func() `signal:apiCertIssue`
_ func(userID string) `signal:userChanged` _ func(userID string) `signal:userChanged`
_ bool `property:"isAllMailVisible"`
_ func(isDisabled bool) `slot:"changeIsAllMailVisible"`
} }
func (q *QMLBackend) setup(f *FrontendQt) { func (q *QMLBackend) setup(f *FrontendQt) {
@ -304,4 +307,11 @@ func (q *QMLBackend) setup(f *FrontendQt) {
f.changeKeychain(k) f.changeKeychain(k)
}() }()
}) })
q.SetIsAllMailVisible(f.bridge.IsAllMailVisible())
q.ConnectChangeIsAllMailVisible(func(isVisible bool) {
f.bridge.SetIsAllMailVisible(isVisible)
f.qml.SetIsAllMailVisible(isVisible)
})
} }

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 557 KiB

View File

@ -1,31 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 22.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 1024 1024" style="enable-background:new 0 0 1024 1024;" xml:space="preserve">
<style type="text/css">
.st0{fill:#9397CD;}
.st1{fill:#262A33;}
.st2{fill:#FFFFFF;}
</style>
<g>
<circle class="st0" cx="512.2" cy="512.1" r="512"/>
</g>
<g>
<circle class="st1" cx="850" cy="850" r="174"/>
</g>
<g>
<path class="st2" d="M784.4,773.1h90.7c15.1,0,26.7,3.7,34.8,11.2s12.1,16.8,12.1,27.8c0,9.3-2.9,17.2-8.7,23.8
c-3.8,4.4-9.5,7.9-16.9,10.5c11.3,2.7,19.5,7.4,24.9,14c5.3,6.6,8,14.9,8,24.9c0,8.1-1.9,15.4-5.7,21.9s-8.9,11.6-15.5,15.4
c-4.1,2.4-10.2,4.1-18.4,5.1c-10.9,1.4-18.1,2.1-21.7,2.1h-83.6L784.4,773.1L784.4,773.1z M833.3,834.6h21.1
c7.6,0,12.8-1.3,15.8-3.9c3-2.6,4.4-6.4,4.4-11.3c0-4.6-1.5-8.1-4.4-10.7c-3-2.6-8.1-3.8-15.5-3.8h-21.4L833.3,834.6L833.3,834.6z
M833.3,896.2H858c8.3,0,14.2-1.5,17.6-4.4c3.4-3,5.1-6.9,5.1-11.9c0-4.6-1.7-8.4-5.1-11.2c-3.4-2.8-9.3-4.2-17.8-4.2h-24.6
L833.3,896.2L833.3,896.2z"/>
</g>
<g>
<path class="st2" d="M511,263c0,0-136.3-4.5-164.4,146.7v103c0,0,1.2,11,32.2,33.4c31,22.4,111.2,85.4,132.3,85.4
c21,0,101.3-63,132.3-85.4c31-22.4,32.2-33.4,32.2-33.4v-103C647.3,258.5,511,263,511,263z M604.3,465.9H511h-93.3v-56.1
c18.9-75.1,93.3-76.1,93.3-76.1s74.4,1,93.3,76.1V465.9z"/>
<path class="st2" d="M511,654.7c0,0-21.1-2.1-37.7-13.5C456.8,629.7,346.6,551,346.6,551v155.9c0,0,0.9,18.1,20.9,18.1
s143.5,0,143.5,0s123.5,0,143.5,0s20.9-18.1,20.9-18.1V551c0,0-110.2,78.8-126.8,90.2C532.1,652.7,511,654.7,511,654.7z"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.7 KiB

View File

@ -21,14 +21,34 @@
package theme package theme
import ( import (
"os/exec" "os"
"strings" "path/filepath"
"howett.net/plist"
) )
func detectSystemTheme() Theme { func detectSystemTheme() Theme {
out, err := exec.Command("defaults", "read", "-g", "AppleInterfaceStyle").Output() //nolint:gosec home, err := os.UserHomeDir()
if err == nil && strings.TrimSpace(string(out)) == "Dark" { if err != nil {
return Light
}
path := filepath.Join(home, "/Library/Preferences/.GlobalPreferences.plist")
prefFile, err := os.Open(path)
if err != nil {
return Light
}
defer prefFile.Close()
var data struct {
AppleInterfaceStyle string `plist:AppleInterfaceStyle`
}
dec := plist.NewDecoder(prefFile)
err = dec.Decode(&data)
if err == nil && data.AppleInterfaceStyle == "Dark" {
return Dark return Dark
} }
return Light return Light
} }

View File

@ -92,6 +92,8 @@ type Bridger interface {
DisableAutostart() error DisableAutostart() error
GetLastVersion() string GetLastVersion() string
IsFirstStart() bool IsFirstStart() bool
IsAllMailVisible() bool
SetIsAllMailVisible(bool)
} }
type bridgeWrap struct { type bridgeWrap struct {

View File

@ -93,10 +93,9 @@ func newIMAPBackend(
eventListener listener.Listener, eventListener listener.Listener,
listWorkers int, listWorkers int,
) *imapBackend { ) *imapBackend {
return &imapBackend{ ib := &imapBackend{
panicHandler: panicHandler, panicHandler: panicHandler,
bridge: bridge, bridge: bridge,
updates: newIMAPUpdates(),
eventListener: eventListener, eventListener: eventListener,
users: map[string]*imapUser{}, users: map[string]*imapUser{},
@ -106,6 +105,8 @@ func newIMAPBackend(
imapCacheLock: &sync.RWMutex{}, imapCacheLock: &sync.RWMutex{},
listWorkers: listWorkers, listWorkers: listWorkers,
} }
ib.updates = newIMAPUpdates(ib)
return ib
} }
func (ib *imapBackend) getUser(address string) (*imapUser, error) { func (ib *imapBackend) getUser(address string) (*imapUser, error) {

View File

@ -31,6 +31,7 @@ type cacheProvider interface {
type bridger interface { type bridger interface {
GetUser(query string) (bridgeUser, error) GetUser(query string) (bridgeUser, error)
HasError(err error) bool HasError(err error) bool
IsAllMailVisible() bool
} }
type bridgeUser interface { type bridgeUser interface {

View File

@ -197,7 +197,7 @@ func (im *imapMailbox) labelExistingMessage(msg storeMessageProvider) error { //
} }
func (im *imapMailbox) importMessage(kr *crypto.KeyRing, hdr textproto.Header, body []byte, imapFlags []string, date time.Time) error { //nolint:funlen func (im *imapMailbox) importMessage(kr *crypto.KeyRing, hdr textproto.Header, body []byte, imapFlags []string, date time.Time) error { //nolint:funlen
im.log.Info("Importing external message") im.log.WithField("size", len(body)).Info("Importing external message")
var ( var (
seen bool seen bool
@ -251,6 +251,7 @@ func (im *imapMailbox) importMessage(kr *crypto.KeyRing, hdr textproto.Header, b
messageID, err := targetMailbox.ImportMessage(enc, seen, labelIDs, flags, time) messageID, err := targetMailbox.ImportMessage(enc, seen, labelIDs, flags, time)
if err != nil { if err != nil {
log.WithField("enc.size", len(enc)).Error("Import failed")
return err return err
} }

View File

@ -332,7 +332,16 @@ func (im *imapMailbox) labelMessages(uid bool, seqSet *imap.SeqSet, targetLabel
// SearchMessages searches messages. The returned list must contain UIDs if // SearchMessages searches messages. The returned list must contain UIDs if
// uid is set to true, or sequence numbers otherwise. // uid is set to true, or sequence numbers otherwise.
func (im *imapMailbox) SearchMessages(isUID bool, criteria *imap.SearchCriteria) (ids []uint32, err error) { //nolint:gocyclo,funlen func (im *imapMailbox) SearchMessages(isUID bool, criteria *imap.SearchCriteria) (ids []uint32, err error) {
err = im.logCommand(func() error {
var searchError error
ids, searchError = im.searchMessages(isUID, criteria)
return searchError
}, "SEARCH", isUID, criteria.Format())
return ids, err
}
func (im *imapMailbox) searchMessages(isUID bool, criteria *imap.SearchCriteria) (ids []uint32, err error) { //nolint:gocyclo,funlen
// Called from go-imap in goroutines - we need to handle panics for each function. // Called from go-imap in goroutines - we need to handle panics for each function.
defer im.panicHandler.HandlePanic() defer im.panicHandler.HandlePanic()

44
internal/imap/map.go Normal file
View File

@ -0,0 +1,44 @@
// 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 imap
import "sync"
type safeMapOfStrings struct {
data map[string]string
mutex sync.RWMutex
}
func newSafeMapOfString() safeMapOfStrings {
return safeMapOfStrings{
data: map[string]string{},
mutex: sync.RWMutex{},
}
}
func (m *safeMapOfStrings) get(key string) string {
m.mutex.RLock()
defer m.mutex.RUnlock()
return m.data[key]
}
func (m *safeMapOfStrings) set(key, value string) {
m.mutex.Lock()
defer m.mutex.Unlock()
m.data[key] = value
}

View File

@ -23,6 +23,7 @@ import (
"time" "time"
"github.com/ProtonMail/proton-bridge/v2/internal/store" "github.com/ProtonMail/proton-bridge/v2/internal/store"
"github.com/ProtonMail/proton-bridge/v2/pkg/algo"
"github.com/ProtonMail/proton-bridge/v2/pkg/message" "github.com/ProtonMail/proton-bridge/v2/pkg/message"
"github.com/ProtonMail/proton-bridge/v2/pkg/pmapi" "github.com/ProtonMail/proton-bridge/v2/pkg/pmapi"
imap "github.com/emersion/go-imap" imap "github.com/emersion/go-imap"
@ -42,14 +43,16 @@ type imapUpdates struct {
blocking map[string]bool blocking map[string]bool
delayedExpunges map[string][]chan struct{} delayedExpunges map[string][]chan struct{}
ch chan goIMAPBackend.Update ch chan goIMAPBackend.Update
ib *imapBackend
} }
func newIMAPUpdates() *imapUpdates { func newIMAPUpdates(ib *imapBackend) *imapUpdates {
return &imapUpdates{ return &imapUpdates{
lock: &sync.Mutex{}, lock: &sync.Mutex{},
blocking: map[string]bool{}, blocking: map[string]bool{},
delayedExpunges: map[string][]chan struct{}{}, delayedExpunges: map[string][]chan struct{}{},
ch: make(chan goIMAPBackend.Update), ch: make(chan goIMAPBackend.Update),
ib: ib,
} }
} }
@ -113,6 +116,8 @@ func (iu *imapUpdates) CanDelete(mailboxID string) (bool, func()) {
} }
func (iu *imapUpdates) Notice(address, notice string) { func (iu *imapUpdates) Notice(address, notice string) {
l := iu.updateLog(address, "")
l.Info("Notice")
update := new(goIMAPBackend.StatusUpdate) update := new(goIMAPBackend.StatusUpdate)
update.Update = goIMAPBackend.NewUpdate(address, "") update.Update = goIMAPBackend.NewUpdate(address, "")
update.StatusResp = &imap.StatusResp{ update.StatusResp = &imap.StatusResp{
@ -120,7 +125,7 @@ func (iu *imapUpdates) Notice(address, notice string) {
Code: imap.CodeAlert, Code: imap.CodeAlert,
Info: notice, Info: notice,
} }
iu.sendIMAPUpdate(update, false) iu.sendIMAPUpdate(l, update, false)
} }
func (iu *imapUpdates) UpdateMessage( func (iu *imapUpdates) UpdateMessage(
@ -128,14 +133,14 @@ func (iu *imapUpdates) UpdateMessage(
uid, sequenceNumber uint32, uid, sequenceNumber uint32,
msg *pmapi.Message, hasDeletedFlag bool, msg *pmapi.Message, hasDeletedFlag bool,
) { ) {
log.WithFields(logrus.Fields{ l := iu.updateLog(address, mailboxName).
"address": address, WithFields(logrus.Fields{
"mailbox": mailboxName, "seqNum": sequenceNumber,
"seqNum": sequenceNumber, "uid": uid,
"uid": uid, "flags": message.GetFlags(msg),
"flags": message.GetFlags(msg), "deleted": hasDeletedFlag,
"deleted": hasDeletedFlag, })
}).Trace("IDLE update") l.Info("IDLE update")
update := new(goIMAPBackend.MessageUpdate) update := new(goIMAPBackend.MessageUpdate)
update.Update = goIMAPBackend.NewUpdate(address, mailboxName) update.Update = goIMAPBackend.NewUpdate(address, mailboxName)
update.Message = imap.NewMessage(sequenceNumber, []imap.FetchItem{imap.FetchFlags, imap.FetchUid}) update.Message = imap.NewMessage(sequenceNumber, []imap.FetchItem{imap.FetchFlags, imap.FetchUid})
@ -144,26 +149,22 @@ func (iu *imapUpdates) UpdateMessage(
update.Message.Flags = append(update.Message.Flags, imap.DeletedFlag) update.Message.Flags = append(update.Message.Flags, imap.DeletedFlag)
} }
update.Message.Uid = uid update.Message.Uid = uid
iu.sendIMAPUpdate(update, iu.isBlocking(address, mailboxName, operationUpdateMessage)) iu.sendIMAPUpdate(l, update, iu.isBlocking(address, mailboxName, operationUpdateMessage))
} }
func (iu *imapUpdates) DeleteMessage(address, mailboxName string, sequenceNumber uint32) { func (iu *imapUpdates) DeleteMessage(address, mailboxName string, sequenceNumber uint32) {
log.WithFields(logrus.Fields{ l := iu.updateLog(address, mailboxName).
"address": address, WithField("seqNum", sequenceNumber)
"mailbox": mailboxName, l.Info("IDLE delete")
"seqNum": sequenceNumber,
}).Trace("IDLE delete")
update := new(goIMAPBackend.ExpungeUpdate) update := new(goIMAPBackend.ExpungeUpdate)
update.Update = goIMAPBackend.NewUpdate(address, mailboxName) update.Update = goIMAPBackend.NewUpdate(address, mailboxName)
update.SeqNum = sequenceNumber update.SeqNum = sequenceNumber
iu.sendIMAPUpdate(update, iu.isBlocking(address, mailboxName, operationDeleteMessage)) iu.sendIMAPUpdate(l, update, iu.isBlocking(address, mailboxName, operationDeleteMessage))
} }
func (iu *imapUpdates) MailboxCreated(address, mailboxName string) { func (iu *imapUpdates) MailboxCreated(address, mailboxName string) {
log.WithFields(logrus.Fields{ l := iu.updateLog(address, mailboxName)
"address": address, l.Info("IDLE mailbox info")
"mailbox": mailboxName,
}).Trace("IDLE mailbox info")
update := new(goIMAPBackend.MailboxInfoUpdate) update := new(goIMAPBackend.MailboxInfoUpdate)
update.Update = goIMAPBackend.NewUpdate(address, "") update.Update = goIMAPBackend.NewUpdate(address, "")
update.MailboxInfo = &imap.MailboxInfo{ update.MailboxInfo = &imap.MailboxInfo{
@ -171,29 +172,30 @@ func (iu *imapUpdates) MailboxCreated(address, mailboxName string) {
Delimiter: store.PathDelimiter, Delimiter: store.PathDelimiter,
Name: mailboxName, Name: mailboxName,
} }
iu.sendIMAPUpdate(update, false) iu.sendIMAPUpdate(l, update, false)
} }
func (iu *imapUpdates) MailboxStatus(address, mailboxName string, total, unread, unreadSeqNum uint32) { func (iu *imapUpdates) MailboxStatus(address, mailboxName string, total, unread, unreadSeqNum uint32) {
log.WithFields(logrus.Fields{ l := iu.updateLog(address, mailboxName).
"address": address, WithFields(logrus.Fields{
"mailbox": mailboxName, "total": total,
"total": total, "unread": unread,
"unread": unread, "unreadSeqNum": unreadSeqNum,
"unreadSeqNum": unreadSeqNum, })
}).Trace("IDLE status") l.Info("IDLE status")
update := new(goIMAPBackend.MailboxUpdate) update := new(goIMAPBackend.MailboxUpdate)
update.Update = goIMAPBackend.NewUpdate(address, mailboxName) update.Update = goIMAPBackend.NewUpdate(address, mailboxName)
update.MailboxStatus = imap.NewMailboxStatus(mailboxName, []imap.StatusItem{imap.StatusMessages, imap.StatusUnseen}) update.MailboxStatus = imap.NewMailboxStatus(mailboxName, []imap.StatusItem{imap.StatusMessages, imap.StatusUnseen})
update.MailboxStatus.Messages = total update.MailboxStatus.Messages = total
update.MailboxStatus.Unseen = unread update.MailboxStatus.Unseen = unread
update.MailboxStatus.UnseenSeqNum = unreadSeqNum update.MailboxStatus.UnseenSeqNum = unreadSeqNum
iu.sendIMAPUpdate(update, true) iu.sendIMAPUpdate(l, update, true)
} }
func (iu *imapUpdates) sendIMAPUpdate(update goIMAPBackend.Update, isBlocking bool) { func (iu *imapUpdates) sendIMAPUpdate(updateLog *logrus.Entry, update goIMAPBackend.Update, isBlocking bool) {
l := updateLog.WithField("blocking", isBlocking)
if iu.ch == nil { if iu.ch == nil {
log.Trace("IMAP IDLE unavailable") l.Info("IMAP IDLE unavailable")
return return
} }
@ -201,7 +203,7 @@ func (iu *imapUpdates) sendIMAPUpdate(update goIMAPBackend.Update, isBlocking bo
go func() { go func() {
select { select {
case <-time.After(1 * time.Second): case <-time.After(1 * time.Second):
log.Warn("IMAP update could not be sent (timeout)") l.Warn("IMAP update could not be sent (timeout)")
return return
case iu.ch <- update: case iu.ch <- update:
} }
@ -214,7 +216,35 @@ func (iu *imapUpdates) sendIMAPUpdate(update goIMAPBackend.Update, isBlocking bo
select { select {
case <-done: case <-done:
case <-time.After(1 * time.Second): case <-time.After(1 * time.Second):
log.Warn("IMAP update could not be delivered (timeout)") l.Warn("IMAP update could not be delivered (timeout)")
return return
} }
} }
func (iu *imapUpdates) getIDs(address, mailboxName string) (addressID, mailboxID string) {
addressID = "unknown-" + algo.HashBase64SHA256(address)
mailboxID = "unknown-" + algo.HashBase64SHA256(mailboxName)
if iu == nil || iu.ib == nil {
return
}
user, err := iu.ib.getUser(address)
if err != nil || user == nil || user.storeAddress == nil {
return
}
addressID = user.addressID
if v := user.mailboxIDs.get(mailboxName); v != "" {
mailboxID = v
}
return
}
func (iu *imapUpdates) updateLog(address, mailboxName string) *logrus.Entry {
addressID, mailboxID := iu.getIDs(address, mailboxName)
return log.
WithField("address", addressID).
WithField("mailbox", mailboxID)
}

View File

@ -25,7 +25,7 @@ import (
) )
func TestUpdatesCanDelete(t *testing.T) { func TestUpdatesCanDelete(t *testing.T) {
u := newIMAPUpdates() u := newIMAPUpdates(nil)
can, _ := u.CanDelete("mbox") can, _ := u.CanDelete("mbox")
require.True(t, can) require.True(t, can)
@ -38,7 +38,7 @@ func TestUpdatesCanDelete(t *testing.T) {
} }
func TestUpdatesCannotDelete(t *testing.T) { func TestUpdatesCannotDelete(t *testing.T) {
u := newIMAPUpdates() u := newIMAPUpdates(nil)
u.forbidExpunge("mbox") u.forbidExpunge("mbox")
can, wait := u.CanDelete("mbox") can, wait := u.CanDelete("mbox")

View File

@ -53,6 +53,9 @@ type imapUser struct {
// not cause huge slow down as EXPUNGE is implicitly called also after // not cause huge slow down as EXPUNGE is implicitly called also after
// UNSELECT, CLOSE, or LOGOUT. // UNSELECT, CLOSE, or LOGOUT.
appendExpungeLock sync.Mutex appendExpungeLock sync.Mutex
addressID string // cached value for logs to avoid lock
mailboxIDs safeMapOfStrings // cached values for logs to avoid lock
} }
// newIMAPUser returns struct implementing go-imap/user interface. // newIMAPUser returns struct implementing go-imap/user interface.
@ -84,6 +87,8 @@ func newIMAPUser(
storeAddress: storeAddress, storeAddress: storeAddress,
currentAddressLowercase: strings.ToLower(address), currentAddressLowercase: strings.ToLower(address),
addressID: addressID,
mailboxIDs: newSafeMapOfString(),
}, err }, err
} }
@ -128,6 +133,12 @@ func (iu *imapUser) ListMailboxes(showOnlySubcribed bool) ([]goIMAPBackend.Mailb
mailboxes := []goIMAPBackend.Mailbox{} mailboxes := []goIMAPBackend.Mailbox{}
for _, storeMailbox := range iu.storeAddress.ListMailboxes() { for _, storeMailbox := range iu.storeAddress.ListMailboxes() {
iu.mailboxIDs.set(storeMailbox.Name(), storeMailbox.LabelID())
if storeMailbox.LabelID() == pmapi.AllMailLabel && !iu.backend.bridge.IsAllMailVisible() {
continue
}
if showOnlySubcribed && !iu.isSubscribed(storeMailbox.LabelID()) { if showOnlySubcribed && !iu.isSubscribed(storeMailbox.LabelID()) {
continue continue
} }

View File

@ -107,7 +107,7 @@ func (l *Locations) getLicenseFilePath() string {
// GetDependencyLicensesLink returns link to page listing dependencies. // GetDependencyLicensesLink returns link to page listing dependencies.
func (l *Locations) GetDependencyLicensesLink() string { func (l *Locations) GetDependencyLicensesLink() string {
return "https://github.com/ProtonMail/proton-bridge/v2/blob/master/COPYING_NOTES.md#dependencies" return "https://github.com/ProtonMail/proton-bridge/blob/master/COPYING_NOTES.md#dependencies"
} }
// ProvideSettingsPath returns a location for user settings (e.g. ~/.config/<company>/<app>). // ProvideSettingsPath returns a location for user settings (e.g. ~/.config/<company>/<app>).

View File

@ -313,16 +313,16 @@ func (su *smtpUser) Send(returnPath string, to []string, messageReader io.Reader
startTime := time.Now() startTime := time.Now()
for isSending && time.Since(startTime) < 90*time.Second { for isSending && time.Since(startTime) < 90*time.Second {
log.Debug("Message is still in send queue, waiting for a bit") log.Warn("Message is still in send queue, waiting for a bit")
time.Sleep(15 * time.Second) time.Sleep(15 * time.Second)
isSending, wasSent = su.backend.sendRecorder.isSendingOrSent(su.client(), sendRecorderMessageHash) isSending, wasSent = su.backend.sendRecorder.isSendingOrSent(su.client(), sendRecorderMessageHash)
} }
if isSending { if isSending {
log.Debug("Message is still in send queue, returning error to prevent client from adding it to the sent folder prematurely") log.Warn("Message is still in send queue, returning error to prevent client from adding it to the sent folder prematurely")
return errors.New("original message is still being sent") return errors.New("original message is still being sent")
} }
if wasSent { if wasSent {
log.Debug("Message was already sent") log.Warn("Message was already sent")
return nil return nil
} }

View File

@ -21,7 +21,6 @@ import (
"crypto/aes" "crypto/aes"
"crypto/cipher" "crypto/cipher"
"crypto/rand" "crypto/rand"
"crypto/sha256"
"errors" "errors"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
@ -29,6 +28,7 @@ import (
"path/filepath" "path/filepath"
"sync" "sync"
"github.com/ProtonMail/proton-bridge/v2/pkg/algo"
"github.com/ProtonMail/proton-bridge/v2/pkg/semaphore" "github.com/ProtonMail/proton-bridge/v2/pkg/semaphore"
"github.com/ricochet2200/go-disk-usage/du" "github.com/ricochet2200/go-disk-usage/du"
) )
@ -100,13 +100,7 @@ func (c *onDiskCache) Lock(userID string) {
} }
func (c *onDiskCache) Unlock(userID string, passphrase []byte) error { func (c *onDiskCache) Unlock(userID string, passphrase []byte) error {
hash := sha256.New() aes, err := aes.NewCipher(algo.Hash256(passphrase))
if _, err := hash.Write(passphrase); err != nil {
return err
}
aes, err := aes.NewCipher(hash.Sum(nil))
if err != nil { if err != nil {
return err return err
} }
@ -279,9 +273,9 @@ func (c *onDiskCache) update() {
} }
func (c *onDiskCache) getUserPath(userID string) string { func (c *onDiskCache) getUserPath(userID string) string {
return filepath.Join(c.path, getHash(userID)) return filepath.Join(c.path, algo.HashHexSHA256(userID))
} }
func (c *onDiskCache) getMessagePath(userID, messageID string) string { func (c *onDiskCache) getMessagePath(userID, messageID string) string {
return filepath.Join(c.getUserPath(userID), getHash(messageID)) return filepath.Join(c.getUserPath(userID), algo.HashHexSHA256(messageID))
} }

View File

@ -128,7 +128,7 @@ func (mc *mailboxCounts) getPMLabel() *pmapi.Label {
Path: mc.LabelName, Path: mc.LabelName,
Color: mc.Color, Color: mc.Color,
Order: mc.Order, Order: mc.Order,
Type: pmapi.LabelTypeMailbox, Type: pmapi.LabelTypeMailBox,
Exclusive: pmapi.Boolean(mc.IsFolder), Exclusive: pmapi.Boolean(mc.IsFolder),
} }
} }

View File

@ -15,33 +15,36 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
//go:build !windows
// +build !windows
package store package store
import ( import (
"fmt"
"os"
"os/exec"
"runtime" "runtime"
"strconv" "syscall"
"strings"
) )
func uLimit() int { func getCurrentFDLimit() (int, error) {
if runtime.GOOS != "darwin" && runtime.GOOS != "linux" { var limits syscall.Rlimit
return 0 err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &limits)
}
out, err := exec.Command("bash", "-c", "ulimit -n").Output()
if err != nil { if err != nil {
log.Print(err) return 0, err
return 0
} }
outStr := strings.Trim(string(out), " \n") return int(limits.Cur), nil
num, err := strconv.Atoi(outStr) }
if err != nil {
log.Print(err) func countOpenedFDs(limit int) int {
return 0 openedFDs := 0
for i := 0; i < limit; i++ {
_, _, err := syscall.Syscall(syscall.SYS_FCNTL, uintptr(i), uintptr(syscall.F_GETFL), 0)
if err == 0 {
openedFDs++
}
} }
return num
return openedFDs
} }
func isFdCloseToULimit() bool { func isFdCloseToULimit() bool {
@ -49,16 +52,18 @@ func isFdCloseToULimit() bool {
return false return false
} }
pid := fmt.Sprint(os.Getpid()) limit, err := getCurrentFDLimit()
out, err := exec.Command("lsof", "-p", pid).Output() //nolint:gosec
if err != nil { if err != nil {
log.Warn("isFdCloseToULimit: ", err) log.WithError(err).Error("Cannot get current FD limit")
return false return false
} }
lines := strings.Split(string(out), "\n")
fd := len(lines) - 1 openedFDs := countOpenedFDs(limit)
ulimit := uLimit()
log.Info("File descriptor check: num goroutines ", runtime.NumGoroutine(), " fd ", fd, " ulimit ", ulimit) log.
return fd >= int(0.95*float64(ulimit)) WithField("noGoroutines", runtime.NumCgoCall()).
WithField("noFDs", openedFDs).
WithField("limitFD", limit).
Info("File descriptor check")
return openedFDs >= int(0.95*float64(limit))
} }

View File

@ -0,0 +1,23 @@
// 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/>.
//go:build windows
// +build windows
package store
func isFdCloseToULimit() bool { return false }

View File

@ -59,7 +59,7 @@ func (store *Store) createMailbox(name string) error {
Name: name, Name: name,
Color: color, Color: color,
Exclusive: pmapi.Boolean(exclusive), Exclusive: pmapi.Boolean(exclusive),
Type: pmapi.LabelTypeMailbox, Type: pmapi.LabelTypeMailBox,
}) })
return err return err
} }
@ -188,7 +188,7 @@ func (store *Store) createOrUpdateMailboxEvent(label *pmapi.Label) error {
store.lock.Lock() store.lock.Lock()
defer store.lock.Unlock() defer store.lock.Unlock()
if label.Type != pmapi.LabelTypeMailbox { if label.Type != pmapi.LabelTypeMailBox {
return nil return nil
} }

View File

@ -20,7 +20,6 @@ package updater
import ( import (
"io/ioutil" "io/ioutil"
"os" "os"
"os/exec"
"path/filepath" "path/filepath"
"testing" "testing"
@ -39,77 +38,103 @@ const (
func TestSyncFolder(t *testing.T) { func TestSyncFolder(t *testing.T) {
for _, srcType := range []string{EmptyType, FileType, SymlinkType, DirType} { for _, srcType := range []string{EmptyType, FileType, SymlinkType, DirType} {
for _, dstType := range []string{EmptyType, FileType, SymlinkType, DirType} { for _, dstType := range []string{EmptyType, FileType, SymlinkType, DirType} {
require.NoError(t, checkCopyWorks(srcType, dstType)) checkCopyWorks(t, srcType, dstType)
logrus.Warn("OK: from ", srcType, " to ", dstType) logrus.Warn("OK: from ", srcType, " to ", dstType)
} }
} }
} }
func checkCopyWorks(srcType, dstType string) error { func checkCopyWorks(tb testing.TB, srcType, dstType string) {
r := require.New(tb)
dirName := "from_" + srcType + "_to_" + dstType dirName := "from_" + srcType + "_to_" + dstType
AppCacheDir := "/tmp" AppCacheDir := "/tmp"
srcDir := filepath.Join(AppCacheDir, "sync_src", dirName) srcDir := filepath.Join(AppCacheDir, "sync_src", dirName)
destDir := filepath.Join(AppCacheDir, "sync_dst", dirName) destDir := filepath.Join(AppCacheDir, "sync_dst", dirName)
// clear before // clear before
logrus.Info("remove all ", srcDir) r.NoError(os.RemoveAll(srcDir))
err := os.RemoveAll(srcDir) r.NoError(os.RemoveAll(destDir))
if err != nil {
return err
}
logrus.Info("remove all ", destDir)
err = os.RemoveAll(destDir)
if err != nil {
return err
}
// create // create
err = createTestFolder(srcDir, srcType) r.NoError(createTestFolder(srcDir, srcType))
if err != nil { r.NoError(createTestFolder(destDir, dstType))
return err
}
err = createTestFolder(destDir, dstType)
if err != nil {
return err
}
// copy // copy
logrus.Info("Sync from ", srcDir, " to ", destDir) r.NoError(syncFolders(destDir, srcDir))
err = syncFolders(destDir, srcDir)
if err != nil {
return err
}
// Check // Check
logrus.Info("check ", srcDir, " and ", destDir) checkThatFilesAreSame(r, srcDir, destDir)
err = checkThatFilesAreSame(srcDir, destDir)
if err != nil {
return err
}
// clear after // clear after
logrus.Info("remove all ", srcDir) r.NoError(os.RemoveAll(srcDir))
err = os.RemoveAll(srcDir) r.NoError(os.RemoveAll(destDir))
if err != nil {
return err
}
logrus.Info("remove all ", destDir)
err = os.RemoveAll(destDir)
if err != nil {
return err
}
return err
} }
func checkThatFilesAreSame(src, dst string) error { func checkThatFilesAreSame(r *require.Assertions, src, dst string) {
cmd := exec.Command("diff", "-qr", src, dst) //nolint:gosec srcFiles, srcDirs, err := walkDir(src)
cmd.Stderr = logrus.StandardLogger().WriterLevel(logrus.ErrorLevel) r.NoError(err)
cmd.Stdout = logrus.StandardLogger().WriterLevel(logrus.InfoLevel)
return cmd.Run() dstFiles, dstDirs, err := walkDir(dst)
r.NoError(err)
r.ElementsMatch(srcFiles, dstFiles)
r.ElementsMatch(srcDirs, dstDirs)
for _, relPath := range srcFiles {
srcPath := filepath.Join(src, relPath)
r.FileExists(srcPath)
dstPath := filepath.Join(dst, relPath)
r.FileExists(dstPath)
srcInfo, err := os.Lstat(srcPath)
r.NoError(err)
dstInfo, err := os.Lstat(dstPath)
r.NoError(err)
r.Equal(srcInfo.Mode(), dstInfo.Mode())
if srcInfo.Mode()&os.ModeSymlink == os.ModeSymlink {
srcLnk, err := os.Readlink(srcPath)
r.NoError(err)
dstLnk, err := os.Readlink(dstPath)
r.NoError(err)
r.Equal(srcLnk, dstLnk)
} else {
srcContent, err := ioutil.ReadFile(srcPath)
r.NoError(err)
dstContent, err := ioutil.ReadFile(dstPath)
r.NoError(err)
r.Equal(srcContent, dstContent)
}
}
}
func walkDir(dir string) (files, dirs []string, err error) {
err = filepath.Walk(dir, func(path string, info os.FileInfo, errWalk error) error {
if errWalk != nil {
return errWalk
}
relPath, errRel := filepath.Rel(dir, path)
if errRel != nil {
return errRel
}
if info.IsDir() {
dirs = append(dirs, relPath)
} else {
files = append(files, relPath)
}
return nil
})
return
} }
func createTestFolder(dirPath, dirType string) error { func createTestFolder(dirPath, dirType string) error {

41
pkg/algo/hash.go Normal file
View File

@ -0,0 +1,41 @@
// 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 algo
import (
"crypto/sha256"
"encoding/base64"
"encoding/hex"
)
func Hash256(b []byte) []byte {
h := sha256.Sum256(b)
return h[:]
}
func HashBase64SHA256(s string) string {
return base64.StdEncoding.EncodeToString(
Hash256([]byte(s)),
)
}
func HashHexSHA256(s string) string {
return hex.EncodeToString(
Hash256([]byte(s)),
)
}

View File

@ -18,13 +18,13 @@
package keychain package keychain
import ( import (
"os/exec"
"reflect" "reflect"
"github.com/docker/docker-credential-helpers/credentials" "github.com/docker/docker-credential-helpers/credentials"
"github.com/docker/docker-credential-helpers/pass" "github.com/docker/docker-credential-helpers/pass"
"github.com/docker/docker-credential-helpers/secretservice" "github.com/docker/docker-credential-helpers/secretservice"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"golang.org/x/sys/execabs"
) )
const ( const (
@ -40,11 +40,11 @@ func init() { //nolint:gochecknoinits
Helpers[SecretServiceDBus] = newDBusHelper Helpers[SecretServiceDBus] = newDBusHelper
} }
if _, err := exec.LookPath("gnome-keyring"); err == nil && isUsable(newSecretServiceHelper("")) { if _, err := execabs.LookPath("gnome-keyring"); err == nil && isUsable(newSecretServiceHelper("")) {
Helpers[SecretService] = newSecretServiceHelper Helpers[SecretService] = newSecretServiceHelper
} }
if _, err := exec.LookPath("pass"); err == nil && isUsable(newPassHelper("")) { if _, err := execabs.LookPath("pass"); err == nil && isUsable(newPassHelper("")) {
Helpers[Pass] = newPassHelper Helpers[Pass] = newPassHelper
} }

View File

@ -18,8 +18,7 @@
package message package message
import ( import (
"crypto/sha256" "github.com/ProtonMail/proton-bridge/v2/pkg/algo"
"encoding/hex"
) )
type boundary struct { type boundary struct {
@ -31,13 +30,6 @@ func newBoundary(seed string) *boundary {
} }
func (bw *boundary) gen() string { func (bw *boundary) gen() string {
hash := sha256.New() bw.val = algo.HashHexSHA256(bw.val)
if _, err := hash.Write([]byte(bw.val)); err != nil {
panic(err)
}
bw.val = hex.EncodeToString(hash.Sum(nil))
return bw.val return bw.val
} }

View File

@ -155,14 +155,6 @@ func convertForeignEncodings(p *parser.Parser) error {
RegisterContentTypeHandler("text/.*", func(p *parser.Part) error { RegisterContentTypeHandler("text/.*", func(p *parser.Part) error {
return p.ConvertToUTF8() return p.ConvertToUTF8()
}). }).
RegisterDefaultHandler(func(p *parser.Part) error {
// multipart/alternative, for example, can contain extra charset.
if _, params, _ := p.ContentType(); params != nil && params["charset"] != "" {
return p.ConvertToUTF8()
}
return nil
}).
Walk() Walk()
} }

View File

@ -64,6 +64,13 @@ type Client interface {
DeleteLabel(ctx context.Context, labelID string) error DeleteLabel(ctx context.Context, labelID string) error
EmptyFolder(ctx context.Context, labelID string, addressID string) error EmptyFolder(ctx context.Context, labelID string, addressID string) error
// /core/V4/labels routes
ListLabelsOnly(ctx context.Context) ([]*Label, error)
ListFoldersOnly(ctx context.Context) ([]*Label, error)
CreateLabelV4(ctx context.Context, label *Label) (*Label, error)
UpdateLabelV4(ctx context.Context, label *Label) (*Label, error)
DeleteLabelV4(ctx context.Context, labelID string) error
GetMailSettings(ctx context.Context) (MailSettings, error) GetMailSettings(ctx context.Context) (MailSettings, error)
GetContactEmailByEmail(context.Context, string, int, int) ([]ContactEmail, error) GetContactEmailByEmail(context.Context, string, int, int) ([]ContactEmail, error)
GetContactByID(context.Context, string) (Contact, error) GetContactByID(context.Context, string) (Contact, error)

View File

@ -18,13 +18,13 @@
package pmapi package pmapi
import ( import (
"crypto/sha256"
"crypto/tls" "crypto/tls"
"crypto/x509" "crypto/x509"
"encoding/base64"
"errors" "errors"
"fmt" "fmt"
"net" "net"
"github.com/ProtonMail/proton-bridge/v2/pkg/algo"
) )
// ErrTLSMismatch indicates that no TLS fingerprint match could be found. // ErrTLSMismatch indicates that no TLS fingerprint match could be found.
@ -63,6 +63,5 @@ func (p *pinChecker) checkCertificate(conn net.Conn) error {
} }
func certFingerprint(cert *x509.Certificate) string { func certFingerprint(cert *x509.Certificate) string {
hash := sha256.Sum256(cert.RawSubjectPublicKeyInfo) return fmt.Sprintf(`pin-sha256=%q`, algo.HashBase64SHA256(string(cert.RawSubjectPublicKeyInfo)))
return fmt.Sprintf(`pin-sha256=%q`, base64.StdEncoding.EncodeToString(hash[:]))
} }

Some files were not shown because too many files have changed in this diff Show More