mirror of
https://github.com/ProtonMail/proton-bridge.git
synced 2025-12-10 12:46:46 +00:00
Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 70645c1732 | |||
| 1055e60d27 | |||
| e04196f8a0 | |||
| 11a0dec047 | |||
| b9740e1b7d | |||
| f0695eb870 | |||
| a40018cdf9 | |||
| 5b7eabe21a | |||
| d5d60aa11b | |||
| a62fa132e6 | |||
| 052395f917 |
@ -20,9 +20,6 @@ issues:
|
|||||||
- gochecknoglobals
|
- gochecknoglobals
|
||||||
- gochecknoinits
|
- gochecknoinits
|
||||||
- gosec
|
- gosec
|
||||||
- path: pkg/message/rfc5322
|
|
||||||
linters:
|
|
||||||
- dupl
|
|
||||||
|
|
||||||
linters-settings:
|
linters-settings:
|
||||||
godox:
|
godox:
|
||||||
|
|||||||
18
Changelog.md
18
Changelog.md
@ -1,9 +1,21 @@
|
|||||||
# ProtonMail Bridge Changelog
|
# ProtonMail Bridge and Import-Export app Changelog
|
||||||
|
|
||||||
Changelog [format](http://keepachangelog.com/en/1.0.0/)
|
Changelog [format](http://keepachangelog.com/en/1.0.0/)
|
||||||
|
|
||||||
## Unreleased
|
## [IE 1.2.1] Elbe
|
||||||
|
|
||||||
|
### Added
|
||||||
|
* GODT-799 Skipped messages do not change total counts but shows as separate number.
|
||||||
|
|
||||||
|
## Fixed
|
||||||
|
* GODT-799 Fix skipping unwanted folders importing from mbox files.
|
||||||
|
* GODT-769 Close connection before deleting labels to prevent panics accessing deleted bucket.
|
||||||
|
|
||||||
|
### Removed
|
||||||
|
* GODT-766 Remove GUI popup for IMAP TLS error.
|
||||||
|
|
||||||
|
|
||||||
|
## [Bridge 1.5.0] Golden Gate
|
||||||
### Changed
|
### Changed
|
||||||
* Updated go-mbox dependency back to upstream.
|
* Updated go-mbox dependency back to upstream.
|
||||||
|
|
||||||
@ -11,6 +23,8 @@ Changelog [format](http://keepachangelog.com/en/1.0.0/)
|
|||||||
* GODT-847 Waiting for unilateral update during deleting the message.
|
* GODT-847 Waiting for unilateral update during deleting the message.
|
||||||
* GODT-849 Show in error counts in the end also lost messages.
|
* GODT-849 Show in error counts in the end also lost messages.
|
||||||
* GODT-835 Do not include conversation ID in references to show properly conversation threads in clients.
|
* GODT-835 Do not include conversation ID in references to show properly conversation threads in clients.
|
||||||
|
* GODT-685 Improve deb packaging regarding dejavu font
|
||||||
|
|
||||||
|
|
||||||
## [IE 1.2.0] Elbe
|
## [IE 1.2.0] Elbe
|
||||||
|
|
||||||
|
|||||||
7
Makefile
7
Makefile
@ -11,7 +11,7 @@ TARGET_OS?=${GOOS}
|
|||||||
|
|
||||||
# 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?=1.5.0-git
|
BRIDGE_APP_VERSION?=1.5.0-git
|
||||||
IE_APP_VERSION?=1.2.0-git
|
IE_APP_VERSION?=1.2.1-git
|
||||||
APP_VERSION:=${BRIDGE_APP_VERSION}
|
APP_VERSION:=${BRIDGE_APP_VERSION}
|
||||||
SRC_ICO:=logo.ico
|
SRC_ICO:=logo.ico
|
||||||
SRC_ICNS:=Bridge.icns
|
SRC_ICNS:=Bridge.icns
|
||||||
@ -280,8 +280,3 @@ clean: clean-vendor
|
|||||||
rm -rf cmd/Import-Export/deploy
|
rm -rf cmd/Import-Export/deploy
|
||||||
rm -f build last.log mem.pprof main.go
|
rm -f build last.log mem.pprof main.go
|
||||||
rm -rf logo.ico icon.rc icon_windows.syso internal/frontend/qt/icon_windows.syso
|
rm -rf logo.ico icon.rc icon_windows.syso internal/frontend/qt/icon_windows.syso
|
||||||
|
|
||||||
.PHONY: generate
|
|
||||||
generate:
|
|
||||||
go generate ./...
|
|
||||||
$(MAKE) add-license
|
|
||||||
|
|||||||
6
go.mod
6
go.mod
@ -18,13 +18,13 @@ require (
|
|||||||
github.com/ProtonMail/go-apple-mobileconfig v0.0.0-20160701194735-7ea9927a11f6
|
github.com/ProtonMail/go-apple-mobileconfig v0.0.0-20160701194735-7ea9927a11f6
|
||||||
github.com/ProtonMail/go-autostart v0.0.0-20181114175602-c5272053443a
|
github.com/ProtonMail/go-autostart v0.0.0-20181114175602-c5272053443a
|
||||||
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.2.0
|
||||||
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.0.1
|
github.com/ProtonMail/gopenpgp/v2 v2.0.1
|
||||||
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
|
||||||
github.com/allan-simon/go-singleinstance v0.0.0-20160830203053-79edcfdc2dfc
|
github.com/allan-simon/go-singleinstance v0.0.0-20160830203053-79edcfdc2dfc
|
||||||
github.com/antlr/antlr4 v0.0.0-20201020194047-0a7eaede42b0
|
|
||||||
github.com/certifi/gocertifi v0.0.0-20200211180108-c7c1fbc02894 // indirect
|
github.com/certifi/gocertifi v0.0.0-20200211180108-c7c1fbc02894 // indirect
|
||||||
github.com/chzyer/logex v1.1.10 // indirect
|
github.com/chzyer/logex v1.1.10 // indirect
|
||||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1 // indirect
|
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1 // indirect
|
||||||
@ -60,7 +60,7 @@ require (
|
|||||||
github.com/nsf/jsondiff v0.0.0-20200515183724-f29ed568f4ce
|
github.com/nsf/jsondiff v0.0.0-20200515183724-f29ed568f4ce
|
||||||
github.com/olekukonko/tablewriter v0.0.4 // indirect
|
github.com/olekukonko/tablewriter v0.0.4 // indirect
|
||||||
github.com/pkg/errors v0.9.1
|
github.com/pkg/errors v0.9.1
|
||||||
github.com/sirupsen/logrus v1.6.0
|
github.com/sirupsen/logrus v1.7.0
|
||||||
github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966
|
github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966
|
||||||
github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf // indirect
|
github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf // indirect
|
||||||
github.com/stretchr/testify v1.6.1
|
github.com/stretchr/testify v1.6.1
|
||||||
@ -75,7 +75,7 @@ require (
|
|||||||
|
|
||||||
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-20201016095853-a7520cc904d3
|
github.com/emersion/go-imap => github.com/ProtonMail/go-imap v0.0.0-20201102134601-418cd74e9474
|
||||||
github.com/emersion/go-smtp => github.com/ProtonMail/go-smtp v0.0.0-20181206232543-8261df20d309
|
github.com/emersion/go-smtp => github.com/ProtonMail/go-smtp v0.0.0-20181206232543-8261df20d309
|
||||||
github.com/jameskeane/bcrypt => github.com/ProtonMail/bcrypt v0.0.0-20170924085257-7509ea014998
|
github.com/jameskeane/bcrypt => github.com/ProtonMail/bcrypt v0.0.0-20170924085257-7509ea014998
|
||||||
golang.org/x/crypto => github.com/ProtonMail/crypto v0.0.0-20200818122824-ed5d25e28db8
|
golang.org/x/crypto => github.com/ProtonMail/crypto v0.0.0-20200818122824-ed5d25e28db8
|
||||||
|
|||||||
16
go.sum
16
go.sum
@ -15,12 +15,14 @@ github.com/ProtonMail/go-apple-mobileconfig v0.0.0-20160701194735-7ea9927a11f6 h
|
|||||||
github.com/ProtonMail/go-apple-mobileconfig v0.0.0-20160701194735-7ea9927a11f6/go.mod h1:EtDfBMIDWmVe4viZCuBTEfe3OIIo0ghbpOaAZVO+hVg=
|
github.com/ProtonMail/go-apple-mobileconfig v0.0.0-20160701194735-7ea9927a11f6/go.mod h1:EtDfBMIDWmVe4viZCuBTEfe3OIIo0ghbpOaAZVO+hVg=
|
||||||
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=
|
||||||
github.com/ProtonMail/go-autostart v0.0.0-20181114175602-c5272053443a/go.mod h1:oTGdE7/DlWIr23G0IKW3OXK9wZ5Hw1GGiaJFccTvZi4=
|
github.com/ProtonMail/go-autostart v0.0.0-20181114175602-c5272053443a/go.mod h1:oTGdE7/DlWIr23G0IKW3OXK9wZ5Hw1GGiaJFccTvZi4=
|
||||||
github.com/ProtonMail/go-imap v0.0.0-20201016095853-a7520cc904d3 h1:Jvv9t3rSg/ID3Fh+uYsxgmvNI9fYnlab4vtBsbPtmq8=
|
github.com/ProtonMail/go-imap v0.0.0-20201102134601-418cd74e9474 h1:D0RwDtkBw0Gt7hmbb1ivdEulplJAwu1i2jzh4HM45fo=
|
||||||
github.com/ProtonMail/go-imap v0.0.0-20201016095853-a7520cc904d3/go.mod h1:yKASt+C3ZiDAiCSssxg9caIckWF/JG7ZQTO7GAmvicU=
|
github.com/ProtonMail/go-imap v0.0.0-20201102134601-418cd74e9474/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=
|
||||||
github.com/ProtonMail/go-imap-id v0.0.0-20190926060100-f94a56b9ecde/go.mod h1:795VPXcRUIQ9JyMNHP4el582VokQfippgjkQP3Gk0r0=
|
github.com/ProtonMail/go-imap-id v0.0.0-20190926060100-f94a56b9ecde/go.mod h1:795VPXcRUIQ9JyMNHP4el582VokQfippgjkQP3Gk0r0=
|
||||||
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-rfc5322 v0.2.0 h1:tndoDGFtiCvESta9KLUeMksojz8qf76PefnkoQ+fqeg=
|
||||||
|
github.com/ProtonMail/go-rfc5322 v0.2.0/go.mod h1:mzZWlMWnQJuYLL7JpzuPF5+FimV2lZ9f0jeq24kJjpU=
|
||||||
github.com/ProtonMail/go-smtp v0.0.0-20181206232543-8261df20d309 h1:2pzfKjhBjSnw3BgmfTYRFQr1rFGxhfhUY0KKkg+RYxE=
|
github.com/ProtonMail/go-smtp v0.0.0-20181206232543-8261df20d309 h1:2pzfKjhBjSnw3BgmfTYRFQr1rFGxhfhUY0KKkg+RYxE=
|
||||||
github.com/ProtonMail/go-smtp v0.0.0-20181206232543-8261df20d309/go.mod h1:6UoBvDAMA/cTBwS3Y7tGpKnY5RH1F1uYHschT6eqAkI=
|
github.com/ProtonMail/go-smtp v0.0.0-20181206232543-8261df20d309/go.mod h1:6UoBvDAMA/cTBwS3Y7tGpKnY5RH1F1uYHschT6eqAkI=
|
||||||
github.com/ProtonMail/go-vcard v0.0.0-20180326232728-33aaa0a0c8a5 h1:Uga1DHFN4GUxuDQr0F71tpi8I9HqPIlZodZAI1lR6VQ=
|
github.com/ProtonMail/go-vcard v0.0.0-20180326232728-33aaa0a0c8a5 h1:Uga1DHFN4GUxuDQr0F71tpi8I9HqPIlZodZAI1lR6VQ=
|
||||||
@ -37,8 +39,8 @@ github.com/allan-simon/go-singleinstance v0.0.0-20160830203053-79edcfdc2dfc h1:m
|
|||||||
github.com/allan-simon/go-singleinstance v0.0.0-20160830203053-79edcfdc2dfc/go.mod h1:qqsTQiwdyqxU05iDCsi0oN3P4nrVxAmn8xCtODDSf/U=
|
github.com/allan-simon/go-singleinstance v0.0.0-20160830203053-79edcfdc2dfc/go.mod h1:qqsTQiwdyqxU05iDCsi0oN3P4nrVxAmn8xCtODDSf/U=
|
||||||
github.com/andybalholm/cascadia v1.1.0 h1:BuuO6sSfQNFRu1LppgbD25Hr2vLYW25JvxHs5zzsLTo=
|
github.com/andybalholm/cascadia v1.1.0 h1:BuuO6sSfQNFRu1LppgbD25Hr2vLYW25JvxHs5zzsLTo=
|
||||||
github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
|
github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
|
||||||
github.com/antlr/antlr4 v0.0.0-20201020194047-0a7eaede42b0 h1:7RW94Pqb4Twsfpz42ALQ+sD0cUUpN8HF4uzKyQf2D8Y=
|
github.com/antlr/antlr4 v0.0.0-20201029161626-9a95f0cc3d7c h1:j/C2kxPfyE0d87/ggAjIsCV5Cdkqmjb+O0W8W+1J+IY=
|
||||||
github.com/antlr/antlr4 v0.0.0-20201020194047-0a7eaede42b0/go.mod h1:T7PbCXFs94rrTttyxjbyT5+/1V8T2TYDejxUfHJjw1Y=
|
github.com/antlr/antlr4 v0.0.0-20201029161626-9a95f0cc3d7c/go.mod h1:T7PbCXFs94rrTttyxjbyT5+/1V8T2TYDejxUfHJjw1Y=
|
||||||
github.com/certifi/gocertifi v0.0.0-20200211180108-c7c1fbc02894 h1:JLaf/iINcLyjwbtTsCJjc6rtlASgHeIJPrB6QmwURnA=
|
github.com/certifi/gocertifi v0.0.0-20200211180108-c7c1fbc02894 h1:JLaf/iINcLyjwbtTsCJjc6rtlASgHeIJPrB6QmwURnA=
|
||||||
github.com/certifi/gocertifi v0.0.0-20200211180108-c7c1fbc02894/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA=
|
github.com/certifi/gocertifi v0.0.0-20200211180108-c7c1fbc02894/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA=
|
||||||
github.com/chzyer/logex v1.1.10 h1:Swpa1K6QvQznwJRcfTfQJmTE72DqScAa40E+fbHEXEE=
|
github.com/chzyer/logex v1.1.10 h1:Swpa1K6QvQznwJRcfTfQJmTE72DqScAa40E+fbHEXEE=
|
||||||
@ -109,8 +111,6 @@ github.com/keybase/go-keychain v0.0.0-20200502122510-cda31fe0c86d/go.mod h1:W6Eb
|
|||||||
github.com/keybase/go.dbus v0.0.0-20200324223359-a94be52c0b03/go.mod h1:a8clEhrrGV/d76/f9r2I41BwANMihfZYV9C223vaxqE=
|
github.com/keybase/go.dbus v0.0.0-20200324223359-a94be52c0b03/go.mod h1:a8clEhrrGV/d76/f9r2I41BwANMihfZYV9C223vaxqE=
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8=
|
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
|
||||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
@ -148,8 +148,8 @@ github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5I
|
|||||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||||
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
|
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
|
||||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||||
github.com/sirupsen/logrus v1.6.0 h1:UBcNElsrwanuuMsnGSlYmtmgbb23qDR5dG+6X6Oo89I=
|
github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM=
|
||||||
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
|
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||||
github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 h1:JIAuq3EEf9cgbU6AtGPK4CTG3Zf6CKMNqf0MHTggAUA=
|
github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 h1:JIAuq3EEf9cgbU6AtGPK4CTG3Zf6CKMNqf0MHTggAUA=
|
||||||
github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966/go.mod h1:sUM3LWHvSMaG192sy56D9F7CNvL7jUJVXoqM1QKLnog=
|
github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966/go.mod h1:sUM3LWHvSMaG192sy56D9F7CNvL7jUJVXoqM1QKLnog=
|
||||||
github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf h1:pvbZ0lM0XWPBqUKqFU8cmavspvIl9nulOYwdy6IFRRo=
|
github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf h1:pvbZ0lM0XWPBqUKqFU8cmavspvIl9nulOYwdy6IFRRo=
|
||||||
|
|||||||
@ -15,8 +15,8 @@
|
|||||||
// 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 ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
// along with ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
// Code generated by ./credits.sh at Wed Nov 4 12:24:36 PM CET 2020. DO NOT EDIT.
|
// Code generated by ./credits.sh at Wed Nov 4 13:57:47 CET 2020. DO NOT EDIT.
|
||||||
|
|
||||||
package bridge
|
package bridge
|
||||||
|
|
||||||
const Credits = "github.com/0xAX/notificator;github.com/abiosoft/ishell;github.com/abiosoft/readline;github.com/allan-simon/go-singleinstance;github.com/antlr/antlr4;github.com/certifi/gocertifi;github.com/chzyer/logex;github.com/chzyer/test;github.com/cucumber/godog;github.com/docker/docker-credential-helpers;github.com/emersion/go-imap;github.com/emersion/go-imap-appendlimit;github.com/emersion/go-imap-idle;github.com/emersion/go-imap-move;github.com/emersion/go-imap-quota;github.com/emersion/go-imap-specialuse;github.com/emersion/go-imap-unselect;github.com/emersion/go-mbox;github.com/emersion/go-message;github.com/emersion/go-sasl;github.com/emersion/go-smtp;github.com/emersion/go-textwrapper;github.com/emersion/go-vcard;github.com/fatih/color;github.com/flynn-archive/go-shlex;github.com/getsentry/raven-go;github.com/golang/mock;github.com/google/go-cmp;github.com/google/uuid;github.com/gopherjs/gopherjs;github.com/go-resty/resty/v2;github.com/hashicorp/go-multierror;github.com/jameskeane/bcrypt;github.com/jaytaylor/html2text;github.com/kardianos/osext;github.com/keybase/go-keychain;github.com/logrusorgru/aurora;github.com/Masterminds/semver/v3;github.com/mattn/go-runewidth;github.com/miekg/dns;github.com/myesui/uuid;github.com/nsf/jsondiff;github.com/olekukonko/tablewriter;github.com/pkg/errors;github.com/ProtonMail/bcrypt;github.com/ProtonMail/crypto;github.com/ProtonMail/docker-credential-helpers;github.com/ProtonMail/go-appdir;github.com/ProtonMail/go-apple-mobileconfig;github.com/ProtonMail/go-autostart;github.com/ProtonMail/go-imap;github.com/ProtonMail/go-imap-id;github.com/ProtonMail/gopenpgp/v2;github.com/ProtonMail/go-smtp;github.com/ProtonMail/go-vcard;github.com/PuerkitoBio/goquery;github.com/sirupsen/logrus;github.com/skratchdot/open-golang;github.com/ssor/bom;github.com/stretchr/testify;github.com/therecipe/qt;github.com/twinj/uuid;github.com/urfave/cli;go.etcd.io/bbolt;golang.org/x/crypto;golang.org/x/net;golang.org/x/text;gopkg.in/stretchr/testify.v1;;Font Awesome 4.7.0;;Qt 5.13 by Qt group;"
|
const Credits = "github.com/0xAX/notificator;github.com/Masterminds/semver/v3;github.com/ProtonMail/bcrypt;github.com/ProtonMail/crypto;github.com/ProtonMail/docker-credential-helpers;github.com/ProtonMail/go-appdir;github.com/ProtonMail/go-apple-mobileconfig;github.com/ProtonMail/go-autostart;github.com/ProtonMail/go-imap;github.com/ProtonMail/go-imap-id;github.com/ProtonMail/go-smtp;github.com/ProtonMail/go-vcard;github.com/ProtonMail/gopenpgp/v2;github.com/PuerkitoBio/goquery;github.com/abiosoft/ishell;github.com/abiosoft/readline;github.com/allan-simon/go-singleinstance;github.com/antlr/antlr4;github.com/certifi/gocertifi;github.com/chzyer/logex;github.com/chzyer/test;github.com/cucumber/godog;github.com/docker/docker-credential-helpers;github.com/emersion/go-imap;github.com/emersion/go-imap-appendlimit;github.com/emersion/go-imap-idle;github.com/emersion/go-imap-move;github.com/emersion/go-imap-quota;github.com/emersion/go-imap-specialuse;github.com/emersion/go-imap-unselect;github.com/emersion/go-mbox;github.com/emersion/go-message;github.com/emersion/go-sasl;github.com/emersion/go-smtp;github.com/emersion/go-textwrapper;github.com/emersion/go-vcard;github.com/fatih/color;github.com/flynn-archive/go-shlex;github.com/getsentry/raven-go;github.com/go-resty/resty/v2;github.com/golang/mock;github.com/google/go-cmp;github.com/google/uuid;github.com/gopherjs/gopherjs;github.com/hashicorp/go-multierror;github.com/jameskeane/bcrypt;github.com/jaytaylor/html2text;github.com/kardianos/osext;github.com/keybase/go-keychain;github.com/logrusorgru/aurora;github.com/mattn/go-runewidth;github.com/miekg/dns;github.com/myesui/uuid;github.com/nsf/jsondiff;github.com/olekukonko/tablewriter;github.com/pkg/errors;github.com/sirupsen/logrus;github.com/skratchdot/open-golang;github.com/ssor/bom;github.com/stretchr/testify;github.com/therecipe/qt;github.com/twinj/uuid;github.com/urfave/cli;go.etcd.io/bbolt;golang.org/x/crypto;golang.org/x/net;golang.org/x/text;gopkg.in/stretchr/testify.v1;;Font Awesome 4.7.0;;Qt 5.13 by Qt group;"
|
||||||
|
|||||||
@ -40,7 +40,6 @@ const (
|
|||||||
NoActiveKeyForRecipientEvent = "noActiveKeyForRecipient"
|
NoActiveKeyForRecipientEvent = "noActiveKeyForRecipient"
|
||||||
UpgradeApplicationEvent = "upgradeApplication"
|
UpgradeApplicationEvent = "upgradeApplication"
|
||||||
TLSCertIssue = "tlsCertPinningIssue"
|
TLSCertIssue = "tlsCertPinningIssue"
|
||||||
IMAPTLSBadCert = "imapTLSBadCert"
|
|
||||||
|
|
||||||
// LogoutEventTimeout is the minimum time to permit between logout events being sent.
|
// LogoutEventTimeout is the minimum time to permit between logout events being sent.
|
||||||
LogoutEventTimeout = 3 * time.Minute
|
LogoutEventTimeout = 3 * time.Minute
|
||||||
|
|||||||
@ -184,9 +184,17 @@ func (f *frontendCLI) setTransferRules(t *transfer.Transfer) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (f *frontendCLI) printTransferProgress(progress *transfer.Progress) {
|
func (f *frontendCLI) printTransferProgress(progress *transfer.Progress) {
|
||||||
failed, imported, exported, added, total := progress.GetCounts()
|
counts := progress.GetCounts()
|
||||||
if total != 0 {
|
if counts.Total != 0 {
|
||||||
f.Println(fmt.Sprintf("Progress update: %d (%d / %d) / %d, failed: %d", imported, exported, added, total, failed))
|
f.Println(fmt.Sprintf(
|
||||||
|
"Progress update: %d (%d / %d) / %d, skipped: %d, failed: %d",
|
||||||
|
counts.Imported,
|
||||||
|
counts.Exported,
|
||||||
|
counts.Added,
|
||||||
|
counts.Total,
|
||||||
|
counts.Skipped,
|
||||||
|
counts.Failed,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
if progress.IsPaused() {
|
if progress.IsPaused() {
|
||||||
|
|||||||
@ -237,13 +237,6 @@ Item {
|
|||||||
winMain.tlsBarState="notOK"
|
winMain.tlsBarState="notOK"
|
||||||
}
|
}
|
||||||
|
|
||||||
onShowIMAPCertTroubleshoot : {
|
|
||||||
go.notifyBubble(1, qsTr(
|
|
||||||
"Bridge was unable to establish a connection with your Email client. <br> <a href=\"https://protonmail.com/support/knowledge-base/bridge-ssl-connection-issue\">Learn more</a> <br>",
|
|
||||||
"notification message"
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -599,7 +599,7 @@ Dialog {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Text {
|
Text {
|
||||||
text: qsTr("<b>Import summary:</b><br>Total number of emails: %1<br>Imported emails: %2<br>Errors: %3").arg(go.total).arg(finalReport.imported).arg(go.progressFails)
|
text: qsTr("<b>Import summary:</b><br>Total number of emails: %1<br>Imported emails: %2<br>Filtered out emails: %3<br>Errors: %4").arg(go.total).arg(go.progressImported).arg(go.progressSkipped).arg(go.progressFails)
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
textFormat: Text.RichText
|
textFormat: Text.RichText
|
||||||
horizontalAlignment: Text.AlignHCenter
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
|||||||
@ -122,7 +122,6 @@ Window {
|
|||||||
ListElement { title: "Minimize this" }
|
ListElement { title: "Minimize this" }
|
||||||
ListElement { title: "SendAlertPopup" }
|
ListElement { title: "SendAlertPopup" }
|
||||||
ListElement { title: "TLSCertError" }
|
ListElement { title: "TLSCertError" }
|
||||||
ListElement { title: "IMAPCertError" }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ListView {
|
ListView {
|
||||||
@ -209,9 +208,6 @@ Window {
|
|||||||
case "TLSCertError" :
|
case "TLSCertError" :
|
||||||
go.showCertIssue()
|
go.showCertIssue()
|
||||||
break;
|
break;
|
||||||
case "IMAPCertError" :
|
|
||||||
go.showIMAPCertTroubleshoot()
|
|
||||||
break;
|
|
||||||
default :
|
default :
|
||||||
console.log("Not implemented " + data)
|
console.log("Not implemented " + data)
|
||||||
}
|
}
|
||||||
@ -314,7 +310,6 @@ Window {
|
|||||||
signal failedAutostartCode(string code)
|
signal failedAutostartCode(string code)
|
||||||
|
|
||||||
signal showCertIssue()
|
signal showCertIssue()
|
||||||
signal showIMAPCertTroubleshoot()
|
|
||||||
|
|
||||||
signal updateFinished(bool hasError)
|
signal updateFinished(bool hasError)
|
||||||
|
|
||||||
|
|||||||
@ -840,6 +840,8 @@ Window {
|
|||||||
|
|
||||||
property real progress: 0.0
|
property real progress: 0.0
|
||||||
property int progressFails: 0
|
property int progressFails: 0
|
||||||
|
property int progressImported: 0
|
||||||
|
property int progressSkipped: 0
|
||||||
property string progressDescription: "nothing"
|
property string progressDescription: "nothing"
|
||||||
property string progressInit: "init"
|
property string progressInit: "init"
|
||||||
property int total: 42
|
property int total: 42
|
||||||
@ -1011,6 +1013,8 @@ Window {
|
|||||||
property SequentialAnimation animateProgressBar : SequentialAnimation {
|
property SequentialAnimation animateProgressBar : SequentialAnimation {
|
||||||
id: apb
|
id: apb
|
||||||
property real speedup : 1.0;
|
property real speedup : 1.0;
|
||||||
|
PropertyAnimation{ target: go; properties: "progressSkipped"; to: 0; duration: 1; }
|
||||||
|
PropertyAnimation{ target: go; properties: "progressImported"; to: 0; duration: 1; }
|
||||||
PropertyAnimation{ target: go; properties: "importLogFileName"; to: ""; duration: 1; }
|
PropertyAnimation{ target: go; properties: "importLogFileName"; to: ""; duration: 1; }
|
||||||
PropertyAnimation{ target: go; properties: "progressDescription"; to: go.progressInit; duration: 1; }
|
PropertyAnimation{ target: go; properties: "progressDescription"; to: go.progressInit; duration: 1; }
|
||||||
PropertyAnimation{ duration: 2000/apb.speedup; }
|
PropertyAnimation{ duration: 2000/apb.speedup; }
|
||||||
@ -1024,6 +1028,8 @@ Window {
|
|||||||
PropertyAnimation{ target: go; properties: "progress"; to: 0.01; duration: 1; }
|
PropertyAnimation{ target: go; properties: "progress"; to: 0.01; duration: 1; }
|
||||||
PropertyAnimation{ duration: 1000/apb.speedup; }
|
PropertyAnimation{ duration: 1000/apb.speedup; }
|
||||||
PropertyAnimation{ target: go; properties: "progress"; to: 0.1; duration: 1; }
|
PropertyAnimation{ target: go; properties: "progress"; to: 0.1; duration: 1; }
|
||||||
|
PropertyAnimation{ target: go; properties: "progressSkipped"; to: 12; duration: 1; }
|
||||||
|
PropertyAnimation{ target: go; properties: "progressImported"; to: 13.1; duration: 1; }
|
||||||
PropertyAnimation{ duration: 1000/apb.speedup; }
|
PropertyAnimation{ duration: 1000/apb.speedup; }
|
||||||
PropertyAnimation{ target: go; properties: "progress"; to: 0.3; duration: 1; }
|
PropertyAnimation{ target: go; properties: "progress"; to: 0.3; duration: 1; }
|
||||||
PropertyAnimation{ target: go; properties: "progressFails"; to: 1; duration: 1; }
|
PropertyAnimation{ target: go; properties: "progressFails"; to: 1; duration: 1; }
|
||||||
|
|||||||
@ -21,6 +21,7 @@ package qtcommon
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/therecipe/qt/core"
|
"github.com/therecipe/qt/core"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@ -337,12 +337,14 @@ func (f *FrontendQt) setProgressManager(progress *transfer.Progress) {
|
|||||||
if progress.IsStopped() {
|
if progress.IsStopped() {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
failed, imported, _, _, total := progress.GetCounts()
|
counts := progress.GetCounts()
|
||||||
f.Qml.SetTotal(int(total))
|
f.Qml.SetTotal(int(counts.Total))
|
||||||
f.Qml.SetProgressFails(int(failed))
|
f.Qml.SetProgressImported(int(counts.Imported))
|
||||||
|
f.Qml.SetProgressSkipped(int(counts.Skipped))
|
||||||
|
f.Qml.SetProgressFails(int(counts.Failed))
|
||||||
f.Qml.SetProgressDescription(progress.PauseReason())
|
f.Qml.SetProgressDescription(progress.PauseReason())
|
||||||
if total > 0 {
|
if counts.Total > 0 {
|
||||||
newProgress := float32(imported+failed) / float32(total)
|
newProgress := counts.Progress()
|
||||||
if newProgress >= 0 && newProgress != f.Qml.Progress() {
|
if newProgress >= 0 && newProgress != f.Qml.Progress() {
|
||||||
f.Qml.SetProgress(newProgress)
|
f.Qml.SetProgress(newProgress)
|
||||||
f.Qml.ProgressChanged(newProgress)
|
f.Qml.ProgressChanged(newProgress)
|
||||||
@ -350,8 +352,10 @@ func (f *FrontendQt) setProgressManager(progress *transfer.Progress) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Counts will add lost messages only once the progress is completeled.
|
// Counts will add lost messages only once the progress is completeled.
|
||||||
failed, _, _, _, _ := progress.GetCounts()
|
counts := progress.GetCounts()
|
||||||
f.Qml.SetProgressFails(int(failed))
|
f.Qml.SetProgressImported(int(counts.Imported))
|
||||||
|
f.Qml.SetProgressSkipped(int(counts.Skipped))
|
||||||
|
f.Qml.SetProgressFails(int(counts.Failed))
|
||||||
|
|
||||||
if err := progress.GetFatalError(); err != nil {
|
if err := progress.GetFatalError(); err != nil {
|
||||||
f.Qml.SetProgressDescription(err.Error())
|
f.Qml.SetProgressDescription(err.Error())
|
||||||
|
|||||||
@ -77,6 +77,8 @@ func (f *FrontendQt) StartImport(email string) { // TODO email not needed
|
|||||||
log.Trace("Starting import")
|
log.Trace("Starting import")
|
||||||
|
|
||||||
f.Qml.SetProgressDescription("init") // TODO use const
|
f.Qml.SetProgressDescription("init") // TODO use const
|
||||||
|
f.Qml.SetProgressImported(0)
|
||||||
|
f.Qml.SetProgressSkipped(0)
|
||||||
f.Qml.SetProgressFails(0)
|
f.Qml.SetProgressFails(0)
|
||||||
f.Qml.SetProgress(0.0)
|
f.Qml.SetProgress(0.0)
|
||||||
f.Qml.SetTotal(1)
|
f.Qml.SetTotal(1)
|
||||||
|
|||||||
@ -43,6 +43,8 @@ type GoQMLInterface struct {
|
|||||||
_ string `property:lastError`
|
_ string `property:lastError`
|
||||||
_ float32 `property:progress`
|
_ float32 `property:progress`
|
||||||
_ string `property:progressDescription`
|
_ string `property:progressDescription`
|
||||||
|
_ int `property:progressImported`
|
||||||
|
_ int `property:progressSkipped`
|
||||||
_ int `property:progressFails`
|
_ int `property:progressFails`
|
||||||
_ int `property:total`
|
_ int `property:total`
|
||||||
_ string `property:importLogFileName`
|
_ string `property:importLogFileName`
|
||||||
|
|||||||
@ -40,17 +40,17 @@ import (
|
|||||||
"github.com/ProtonMail/proton-bridge/internal/bridge"
|
"github.com/ProtonMail/proton-bridge/internal/bridge"
|
||||||
"github.com/ProtonMail/proton-bridge/internal/events"
|
"github.com/ProtonMail/proton-bridge/internal/events"
|
||||||
"github.com/ProtonMail/proton-bridge/internal/frontend/autoconfig"
|
"github.com/ProtonMail/proton-bridge/internal/frontend/autoconfig"
|
||||||
"github.com/ProtonMail/proton-bridge/internal/frontend/qt-common"
|
qtcommon "github.com/ProtonMail/proton-bridge/internal/frontend/qt-common"
|
||||||
"github.com/ProtonMail/proton-bridge/internal/frontend/types"
|
"github.com/ProtonMail/proton-bridge/internal/frontend/types"
|
||||||
"github.com/ProtonMail/proton-bridge/internal/preferences"
|
"github.com/ProtonMail/proton-bridge/internal/preferences"
|
||||||
"github.com/ProtonMail/proton-bridge/internal/updates"
|
"github.com/ProtonMail/proton-bridge/internal/updates"
|
||||||
"github.com/ProtonMail/proton-bridge/pkg/config"
|
"github.com/ProtonMail/proton-bridge/pkg/config"
|
||||||
"github.com/ProtonMail/proton-bridge/pkg/ports"
|
|
||||||
"github.com/ProtonMail/proton-bridge/pkg/useragent"
|
|
||||||
"github.com/ProtonMail/proton-bridge/pkg/listener"
|
"github.com/ProtonMail/proton-bridge/pkg/listener"
|
||||||
"github.com/ProtonMail/proton-bridge/pkg/pmapi"
|
"github.com/ProtonMail/proton-bridge/pkg/pmapi"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/ProtonMail/proton-bridge/pkg/ports"
|
||||||
|
"github.com/ProtonMail/proton-bridge/pkg/useragent"
|
||||||
"github.com/kardianos/osext"
|
"github.com/kardianos/osext"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
"github.com/skratchdot/open-golang/open"
|
"github.com/skratchdot/open-golang/open"
|
||||||
"github.com/therecipe/qt/core"
|
"github.com/therecipe/qt/core"
|
||||||
"github.com/therecipe/qt/gui"
|
"github.com/therecipe/qt/gui"
|
||||||
@ -187,7 +187,6 @@ func (s *FrontendQt) watchEvents() {
|
|||||||
updateApplicationCh := s.getEventChannel(events.UpgradeApplicationEvent)
|
updateApplicationCh := s.getEventChannel(events.UpgradeApplicationEvent)
|
||||||
newUserCh := s.getEventChannel(events.UserRefreshEvent)
|
newUserCh := s.getEventChannel(events.UserRefreshEvent)
|
||||||
certIssue := s.getEventChannel(events.TLSCertIssue)
|
certIssue := s.getEventChannel(events.TLSCertIssue)
|
||||||
imapCertIssue := s.getEventChannel(events.IMAPTLSBadCert)
|
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case errorDetails := <-errorCh:
|
case errorDetails := <-errorCh:
|
||||||
@ -227,8 +226,6 @@ func (s *FrontendQt) watchEvents() {
|
|||||||
s.Qml.LoadAccounts()
|
s.Qml.LoadAccounts()
|
||||||
case <-certIssue:
|
case <-certIssue:
|
||||||
s.Qml.ShowCertIssue()
|
s.Qml.ShowCertIssue()
|
||||||
case <-imapCertIssue:
|
|
||||||
s.Qml.ShowIMAPCertTroubleshoot()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -135,7 +135,6 @@ type GoQMLInterface struct {
|
|||||||
_ func(x, y float32) `slot:"saveOutgoingNoEncPopupCoord"`
|
_ func(x, y float32) `slot:"saveOutgoingNoEncPopupCoord"`
|
||||||
_ func(recipient string) `signal:"showNoActiveKeyForRecipient"`
|
_ func(recipient string) `signal:"showNoActiveKeyForRecipient"`
|
||||||
_ func() `signal:"showCertIssue"`
|
_ func() `signal:"showCertIssue"`
|
||||||
_ func() `signal:"ShowIMAPCertTroubleshoot"`
|
|
||||||
|
|
||||||
_ func() `slot:"startUpdate"`
|
_ func() `slot:"startUpdate"`
|
||||||
_ func(hasError bool) `signal:"updateFinished"`
|
_ func(hasError bool) `signal:"updateFinished"`
|
||||||
|
|||||||
@ -28,7 +28,6 @@ import (
|
|||||||
"github.com/ProtonMail/proton-bridge/pkg/listener"
|
"github.com/ProtonMail/proton-bridge/pkg/listener"
|
||||||
"github.com/emersion/go-imap"
|
"github.com/emersion/go-imap"
|
||||||
goIMAPBackend "github.com/emersion/go-imap/backend"
|
goIMAPBackend "github.com/emersion/go-imap/backend"
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type panicHandler interface {
|
type panicHandler interface {
|
||||||
@ -198,11 +197,3 @@ func (ib *imapBackend) monitorDisconnectedUsers() {
|
|||||||
ib.deleteUser(address)
|
ib.deleteUser(address)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ib *imapBackend) upgradeError(err error) {
|
|
||||||
logrus.WithError(err).Error("IMAP connection couldn't be upgraded to TLS during STARTTLS")
|
|
||||||
|
|
||||||
if strings.Contains(err.Error(), "remote error: tls: bad certificate") {
|
|
||||||
ib.eventListener.Emit(events.IMAPTLSBadCert, err.Error())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@ -58,7 +58,6 @@ func NewIMAPServer(debugClient, debugServer bool, port int, tls *tls.Config, ima
|
|||||||
s.AllowInsecureAuth = true
|
s.AllowInsecureAuth = true
|
||||||
s.ErrorLog = newServerErrorLogger("server-imap")
|
s.ErrorLog = newServerErrorLogger("server-imap")
|
||||||
s.AutoLogout = 30 * time.Minute
|
s.AutoLogout = 30 * time.Minute
|
||||||
s.UpgradeError = imapBackend.upgradeError
|
|
||||||
|
|
||||||
serverID := imapid.ID{
|
serverID := imapid.ID{
|
||||||
imapid.FieldName: "ProtonMail Bridge",
|
imapid.FieldName: "ProtonMail Bridge",
|
||||||
|
|||||||
@ -15,8 +15,8 @@
|
|||||||
// 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 ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
// along with ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
// Code generated by ./credits.sh at Wed Nov 4 12:24:36 PM CET 2020. DO NOT EDIT.
|
// Code generated by ./credits.sh at Wed Nov 4 13:57:47 CET 2020. DO NOT EDIT.
|
||||||
|
|
||||||
package importexport
|
package importexport
|
||||||
|
|
||||||
const Credits = "github.com/0xAX/notificator;github.com/abiosoft/ishell;github.com/abiosoft/readline;github.com/allan-simon/go-singleinstance;github.com/antlr/antlr4;github.com/certifi/gocertifi;github.com/chzyer/logex;github.com/chzyer/test;github.com/cucumber/godog;github.com/docker/docker-credential-helpers;github.com/emersion/go-imap;github.com/emersion/go-imap-appendlimit;github.com/emersion/go-imap-idle;github.com/emersion/go-imap-move;github.com/emersion/go-imap-quota;github.com/emersion/go-imap-specialuse;github.com/emersion/go-imap-unselect;github.com/emersion/go-mbox;github.com/emersion/go-message;github.com/emersion/go-sasl;github.com/emersion/go-smtp;github.com/emersion/go-textwrapper;github.com/emersion/go-vcard;github.com/fatih/color;github.com/flynn-archive/go-shlex;github.com/getsentry/raven-go;github.com/golang/mock;github.com/google/go-cmp;github.com/google/uuid;github.com/gopherjs/gopherjs;github.com/go-resty/resty/v2;github.com/hashicorp/go-multierror;github.com/jameskeane/bcrypt;github.com/jaytaylor/html2text;github.com/kardianos/osext;github.com/keybase/go-keychain;github.com/logrusorgru/aurora;github.com/Masterminds/semver/v3;github.com/mattn/go-runewidth;github.com/miekg/dns;github.com/myesui/uuid;github.com/nsf/jsondiff;github.com/olekukonko/tablewriter;github.com/pkg/errors;github.com/ProtonMail/bcrypt;github.com/ProtonMail/crypto;github.com/ProtonMail/docker-credential-helpers;github.com/ProtonMail/go-appdir;github.com/ProtonMail/go-apple-mobileconfig;github.com/ProtonMail/go-autostart;github.com/ProtonMail/go-imap;github.com/ProtonMail/go-imap-id;github.com/ProtonMail/gopenpgp/v2;github.com/ProtonMail/go-smtp;github.com/ProtonMail/go-vcard;github.com/PuerkitoBio/goquery;github.com/sirupsen/logrus;github.com/skratchdot/open-golang;github.com/ssor/bom;github.com/stretchr/testify;github.com/therecipe/qt;github.com/twinj/uuid;github.com/urfave/cli;go.etcd.io/bbolt;golang.org/x/crypto;golang.org/x/net;golang.org/x/text;gopkg.in/stretchr/testify.v1;;Font Awesome 4.7.0;;Qt 5.13 by Qt group;"
|
const Credits = "github.com/0xAX/notificator;github.com/Masterminds/semver/v3;github.com/ProtonMail/bcrypt;github.com/ProtonMail/crypto;github.com/ProtonMail/docker-credential-helpers;github.com/ProtonMail/go-appdir;github.com/ProtonMail/go-apple-mobileconfig;github.com/ProtonMail/go-autostart;github.com/ProtonMail/go-imap;github.com/ProtonMail/go-imap-id;github.com/ProtonMail/go-smtp;github.com/ProtonMail/go-vcard;github.com/ProtonMail/gopenpgp/v2;github.com/PuerkitoBio/goquery;github.com/abiosoft/ishell;github.com/abiosoft/readline;github.com/allan-simon/go-singleinstance;github.com/antlr/antlr4;github.com/certifi/gocertifi;github.com/chzyer/logex;github.com/chzyer/test;github.com/cucumber/godog;github.com/docker/docker-credential-helpers;github.com/emersion/go-imap;github.com/emersion/go-imap-appendlimit;github.com/emersion/go-imap-idle;github.com/emersion/go-imap-move;github.com/emersion/go-imap-quota;github.com/emersion/go-imap-specialuse;github.com/emersion/go-imap-unselect;github.com/emersion/go-mbox;github.com/emersion/go-message;github.com/emersion/go-sasl;github.com/emersion/go-smtp;github.com/emersion/go-textwrapper;github.com/emersion/go-vcard;github.com/fatih/color;github.com/flynn-archive/go-shlex;github.com/getsentry/raven-go;github.com/go-resty/resty/v2;github.com/golang/mock;github.com/google/go-cmp;github.com/google/uuid;github.com/gopherjs/gopherjs;github.com/hashicorp/go-multierror;github.com/jameskeane/bcrypt;github.com/jaytaylor/html2text;github.com/kardianos/osext;github.com/keybase/go-keychain;github.com/logrusorgru/aurora;github.com/mattn/go-runewidth;github.com/miekg/dns;github.com/myesui/uuid;github.com/nsf/jsondiff;github.com/olekukonko/tablewriter;github.com/pkg/errors;github.com/sirupsen/logrus;github.com/skratchdot/open-golang;github.com/ssor/bom;github.com/stretchr/testify;github.com/therecipe/qt;github.com/twinj/uuid;github.com/urfave/cli;go.etcd.io/bbolt;golang.org/x/crypto;golang.org/x/net;golang.org/x/text;gopkg.in/stretchr/testify.v1;;Font Awesome 4.7.0;;Qt 5.13 by Qt group;"
|
||||||
|
|||||||
@ -15,18 +15,14 @@
|
|||||||
// 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 ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
// along with ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
// Code generated by ./release-notes.sh at 'Wed Nov 4 12:24:35 PM CET 2020'. DO NOT EDIT.
|
// Code generated by ./release-notes.sh at 'Wed Nov 11 01:57:14 PM CET 2020'. DO NOT EDIT.
|
||||||
|
|
||||||
package importexport
|
package importexport
|
||||||
|
|
||||||
const ReleaseNotes = `• Improvements to the import from large mbox files with multiple labels
|
const ReleaseNotes = `• Further improvements to address and date parsing
|
||||||
• Not allow to run multiple instances of the app or transfers at the same time
|
• Better handling and displaying of skipped messages
|
||||||
• Various enhancements of the import process related to parsing
|
• Improved error reporting
|
||||||
• Cosmetic GUI changes
|
|
||||||
• Better error handling
|
|
||||||
`
|
`
|
||||||
|
|
||||||
const ReleaseFixedBugs = `• Linux font issues - Fedora specific
|
const ReleaseFixedBugs = `
|
||||||
• App response to the user pausing and canceling import or export
|
|
||||||
• Handling errors during update
|
|
||||||
`
|
`
|
||||||
|
|||||||
@ -21,6 +21,7 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync/atomic"
|
||||||
|
|
||||||
"github.com/ProtonMail/proton-bridge/pkg/pmapi"
|
"github.com/ProtonMail/proton-bridge/pkg/pmapi"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
@ -38,6 +39,8 @@ type Mailbox struct {
|
|||||||
color string
|
color string
|
||||||
|
|
||||||
log *logrus.Entry
|
log *logrus.Entry
|
||||||
|
|
||||||
|
isDeleting atomic.Value
|
||||||
}
|
}
|
||||||
|
|
||||||
func newMailbox(storeAddress *Address, labelID, labelPrefix, labelName, color string) (mb *Mailbox, err error) {
|
func newMailbox(storeAddress *Address, labelID, labelPrefix, labelName, color string) (mb *Mailbox, err error) {
|
||||||
@ -59,6 +62,7 @@ func txNewMailbox(tx *bolt.Tx, storeAddress *Address, labelID, labelPrefix, labe
|
|||||||
color: color,
|
color: color,
|
||||||
log: l,
|
log: l,
|
||||||
}
|
}
|
||||||
|
mb.isDeleting.Store(false)
|
||||||
|
|
||||||
err := initMailboxBucket(tx, mb.getBucketName())
|
err := initMailboxBucket(tx, mb.getBucketName())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -215,6 +219,7 @@ func (storeMailbox *Mailbox) Rename(newName string) error {
|
|||||||
// Deletion has to be propagated to all the same mailboxes in all addresses.
|
// Deletion has to be propagated to all the same mailboxes in all addresses.
|
||||||
// The propagation is processed by the event loop.
|
// The propagation is processed by the event loop.
|
||||||
func (storeMailbox *Mailbox) Delete() error {
|
func (storeMailbox *Mailbox) Delete() error {
|
||||||
|
storeMailbox.isDeleting.Store(true)
|
||||||
return storeMailbox.storeAddress.deleteMailbox(storeMailbox.labelID)
|
return storeMailbox.storeAddress.deleteMailbox(storeMailbox.labelID)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -226,6 +231,14 @@ func (storeMailbox *Mailbox) GetDelimiter() string {
|
|||||||
// deleteMailboxEvent deletes the mailbox bucket.
|
// deleteMailboxEvent deletes the mailbox bucket.
|
||||||
// This is called from the event loop.
|
// This is called from the event loop.
|
||||||
func (storeMailbox *Mailbox) deleteMailboxEvent() error {
|
func (storeMailbox *Mailbox) deleteMailboxEvent() error {
|
||||||
|
if !storeMailbox.isDeleting.Load().(bool) {
|
||||||
|
// Deleting label removes bucket. Any ongoing connection selected
|
||||||
|
// in such mailbox then might panic because of non-existing bucket.
|
||||||
|
// Closing connetions prevents that panic but if the connection
|
||||||
|
// asked for deletion, it should not be closed so it can receive
|
||||||
|
// successful response.
|
||||||
|
storeMailbox.store.user.CloseAllConnections()
|
||||||
|
}
|
||||||
return storeMailbox.db().Update(func(tx *bolt.Tx) error {
|
return storeMailbox.db().Update(func(tx *bolt.Tx) error {
|
||||||
return tx.Bucket(mailboxesBucket).DeleteBucket(storeMailbox.getBucketName())
|
return tx.Bucket(mailboxesBucket).DeleteBucket(storeMailbox.getBucketName())
|
||||||
})
|
})
|
||||||
|
|||||||
@ -5,9 +5,10 @@
|
|||||||
package mocks
|
package mocks
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
reflect "reflect"
|
||||||
|
|
||||||
pmapi "github.com/ProtonMail/proton-bridge/pkg/pmapi"
|
pmapi "github.com/ProtonMail/proton-bridge/pkg/pmapi"
|
||||||
gomock "github.com/golang/mock/gomock"
|
gomock "github.com/golang/mock/gomock"
|
||||||
reflect "reflect"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// MockPanicHandler is a mock of PanicHandler interface
|
// MockPanicHandler is a mock of PanicHandler interface
|
||||||
@ -105,6 +106,18 @@ func (m *MockBridgeUser) EXPECT() *MockBridgeUserMockRecorder {
|
|||||||
return m.recorder
|
return m.recorder
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CloseAllConnections mocks base method
|
||||||
|
func (m *MockBridgeUser) CloseAllConnections() {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
m.ctrl.Call(m, "CloseAllConnections")
|
||||||
|
}
|
||||||
|
|
||||||
|
// CloseAllConnections indicates an expected call of CloseAllConnections
|
||||||
|
func (mr *MockBridgeUserMockRecorder) CloseAllConnections() *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CloseAllConnections", reflect.TypeOf((*MockBridgeUser)(nil).CloseAllConnections))
|
||||||
|
}
|
||||||
|
|
||||||
// CloseConnection mocks base method
|
// CloseConnection mocks base method
|
||||||
func (m *MockBridgeUser) CloseConnection(arg0 string) {
|
func (m *MockBridgeUser) CloseConnection(arg0 string) {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
|
|||||||
@ -5,9 +5,10 @@
|
|||||||
package mocks
|
package mocks
|
||||||
|
|
||||||
import (
|
import (
|
||||||
gomock "github.com/golang/mock/gomock"
|
|
||||||
reflect "reflect"
|
reflect "reflect"
|
||||||
time "time"
|
time "time"
|
||||||
|
|
||||||
|
gomock "github.com/golang/mock/gomock"
|
||||||
)
|
)
|
||||||
|
|
||||||
// MockListener is a mock of Listener interface
|
// MockListener is a mock of Listener interface
|
||||||
|
|||||||
@ -36,6 +36,7 @@ type BridgeUser interface {
|
|||||||
GetPrimaryAddress() string
|
GetPrimaryAddress() string
|
||||||
GetStoreAddresses() []string
|
GetStoreAddresses() []string
|
||||||
UpdateUser() error
|
UpdateUser() error
|
||||||
|
CloseAllConnections()
|
||||||
CloseConnection(string)
|
CloseConnection(string)
|
||||||
Logout() error
|
Logout() error
|
||||||
}
|
}
|
||||||
|
|||||||
@ -58,6 +58,7 @@ type MessageStatus struct {
|
|||||||
targetID string // Message ID at the target (if any).
|
targetID string // Message ID at the target (if any).
|
||||||
bodyHash string // Hash of the message body.
|
bodyHash string // Hash of the message body.
|
||||||
|
|
||||||
|
skipped bool
|
||||||
exported bool
|
exported bool
|
||||||
imported bool
|
imported bool
|
||||||
exportErr error
|
exportErr error
|
||||||
@ -96,7 +97,7 @@ func (status *MessageStatus) setDetailsFromHeader(header mail.Header) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (status *MessageStatus) hasError(includeMissing bool) bool {
|
func (status *MessageStatus) hasError(includeMissing bool) bool {
|
||||||
return status.exportErr != nil || status.importErr != nil || (includeMissing && !status.imported)
|
return status.exportErr != nil || status.importErr != nil || (includeMissing && !status.skipped && !status.imported)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetErrorMessage returns error message.
|
// GetErrorMessage returns error message.
|
||||||
@ -105,6 +106,9 @@ func (status *MessageStatus) GetErrorMessage() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (status *MessageStatus) getErrorMessage(includeMissing bool) string {
|
func (status *MessageStatus) getErrorMessage(includeMissing bool) string {
|
||||||
|
if status.skipped {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
if status.exportErr != nil {
|
if status.exportErr != nil {
|
||||||
return fmt.Sprintf("failed to export: %s", status.exportErr)
|
return fmt.Sprintf("failed to export: %s", status.exportErr)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,9 +5,10 @@
|
|||||||
package mocks
|
package mocks
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
reflect "reflect"
|
||||||
|
|
||||||
pmapi "github.com/ProtonMail/proton-bridge/pkg/pmapi"
|
pmapi "github.com/ProtonMail/proton-bridge/pkg/pmapi"
|
||||||
gomock "github.com/golang/mock/gomock"
|
gomock "github.com/golang/mock/gomock"
|
||||||
reflect "reflect"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// MockPanicHandler is a mock of PanicHandler interface
|
// MockPanicHandler is a mock of PanicHandler interface
|
||||||
|
|||||||
@ -140,6 +140,19 @@ func (p *Progress) addMessage(messageID string, sourceNames, targetNames []strin
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// messageSkipped should be called once the message is skipped due to some
|
||||||
|
// filter such as time or folder and so on.
|
||||||
|
func (p *Progress) messageSkipped(messageID string) {
|
||||||
|
p.lock.Lock()
|
||||||
|
defer p.lock.Unlock()
|
||||||
|
defer p.update()
|
||||||
|
|
||||||
|
p.log.WithField("id", messageID).Debug("Message skipped")
|
||||||
|
|
||||||
|
p.messageStatuses[messageID].skipped = true
|
||||||
|
p.logMessage(messageID)
|
||||||
|
}
|
||||||
|
|
||||||
// messageExported should be called right before message is exported.
|
// messageExported should be called right before message is exported.
|
||||||
func (p *Progress) messageExported(messageID string, body []byte, err error) {
|
func (p *Progress) messageExported(messageID string, body []byte, err error) {
|
||||||
p.lock.Lock()
|
p.lock.Lock()
|
||||||
@ -330,35 +343,40 @@ func (p *Progress) GetFailedMessages() []*MessageStatus {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetCounts returns counts of exported and imported messages.
|
// GetCounts returns counts of exported and imported messages.
|
||||||
func (p *Progress) GetCounts() (failed, imported, exported, added, total uint) {
|
func (p *Progress) GetCounts() ProgressCounts {
|
||||||
p.lock.Lock()
|
p.lock.Lock()
|
||||||
defer p.lock.Unlock()
|
defer p.lock.Unlock()
|
||||||
|
|
||||||
|
counts := ProgressCounts{}
|
||||||
|
|
||||||
// Return counts only once total is estimated or the process already
|
// Return counts only once total is estimated or the process already
|
||||||
// ended (for a case when it ended quickly to report it correctly).
|
// ended (for a case when it ended quickly to report it correctly).
|
||||||
if p.updateCh != nil && !p.messageCounted {
|
if p.updateCh != nil && !p.messageCounted {
|
||||||
return
|
return counts
|
||||||
}
|
}
|
||||||
|
|
||||||
// Include lost messages in the process only when transfer is done.
|
// Include lost messages in the process only when transfer is done.
|
||||||
includeMissing := p.updateCh == nil
|
includeMissing := p.updateCh == nil
|
||||||
|
|
||||||
for _, mailboxCount := range p.messageCounts {
|
for _, mailboxCount := range p.messageCounts {
|
||||||
total += mailboxCount
|
counts.Total += mailboxCount
|
||||||
}
|
}
|
||||||
for _, status := range p.messageStatuses {
|
for _, status := range p.messageStatuses {
|
||||||
added++
|
counts.Added++
|
||||||
|
if status.skipped {
|
||||||
|
counts.Skipped++
|
||||||
|
}
|
||||||
if status.exported {
|
if status.exported {
|
||||||
exported++
|
counts.Exported++
|
||||||
}
|
}
|
||||||
if status.imported {
|
if status.imported {
|
||||||
imported++
|
counts.Imported++
|
||||||
}
|
}
|
||||||
if status.hasError(includeMissing) {
|
if status.hasError(includeMissing) {
|
||||||
failed++
|
counts.Failed++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
return counts
|
||||||
}
|
}
|
||||||
|
|
||||||
// GenerateBugReport generates similar file to import log except private information.
|
// GenerateBugReport generates similar file to import log except private information.
|
||||||
|
|||||||
@ -15,35 +15,21 @@
|
|||||||
// 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 ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
// along with ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
package rfc5322
|
package transfer
|
||||||
|
|
||||||
import (
|
// ProgressCounts holds counts counted by Progress.
|
||||||
"github.com/ProtonMail/proton-bridge/pkg/message/rfc5322/parser"
|
type ProgressCounts struct {
|
||||||
"github.com/sirupsen/logrus"
|
Failed,
|
||||||
)
|
Skipped,
|
||||||
|
Imported,
|
||||||
type fws struct {
|
Exported,
|
||||||
value string
|
Added,
|
||||||
|
Total uint
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *walker) EnterFws(ctx *parser.FwsContext) {
|
// Progress returns ratio between processed messages (fully imported, skipped
|
||||||
logrus.WithField("text", ctx.GetText()).Trace("Entering fws")
|
// and failed ones) and total number of messages as percentage (0 - 1).
|
||||||
|
func (c *ProgressCounts) Progress() float32 {
|
||||||
w.enter(&fws{
|
progressed := c.Imported + c.Skipped + c.Failed
|
||||||
value: ctx.GetText(),
|
return float32(progressed) / float32(c.Total)
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) ExitFws(ctx *parser.FwsContext) {
|
|
||||||
logrus.WithField("text", ctx.GetText()).Trace("Exiting fws")
|
|
||||||
|
|
||||||
type withFws interface {
|
|
||||||
withFws(*fws)
|
|
||||||
}
|
|
||||||
|
|
||||||
res := w.exit().(*fws)
|
|
||||||
|
|
||||||
if parent, ok := w.parent().(withFws); ok {
|
|
||||||
parent.withFws(res)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@ -39,8 +39,8 @@ func TestProgressUpdateCount(t *testing.T) {
|
|||||||
|
|
||||||
progress.finish()
|
progress.finish()
|
||||||
|
|
||||||
_, _, _, _, total := progress.GetCounts() //nolint[dogsled]
|
counts := progress.GetCounts()
|
||||||
r.Equal(t, uint(42), total)
|
r.Equal(t, uint(42), counts.Total)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestProgressAddingMessages(t *testing.T) {
|
func TestProgressAddingMessages(t *testing.T) {
|
||||||
@ -66,13 +66,18 @@ func TestProgressAddingMessages(t *testing.T) {
|
|||||||
progress.messageExported("msg4", []byte(""), errors.New("failed export"))
|
progress.messageExported("msg4", []byte(""), errors.New("failed export"))
|
||||||
progress.messageImported("msg4", "", nil)
|
progress.messageImported("msg4", "", nil)
|
||||||
|
|
||||||
|
// msg5 is skipped.
|
||||||
|
progress.addMessage("msg5", []string{}, []string{})
|
||||||
|
progress.messageSkipped("msg5")
|
||||||
|
|
||||||
progress.finish()
|
progress.finish()
|
||||||
|
|
||||||
failed, imported, exported, added, _ := progress.GetCounts()
|
counts := progress.GetCounts()
|
||||||
a.Equal(t, uint(4), added)
|
a.Equal(t, uint(5), counts.Added)
|
||||||
a.Equal(t, uint(2), exported)
|
a.Equal(t, uint(2), counts.Exported)
|
||||||
a.Equal(t, uint(2), imported)
|
a.Equal(t, uint(2), counts.Imported)
|
||||||
a.Equal(t, uint(3), failed)
|
a.Equal(t, uint(1), counts.Skipped)
|
||||||
|
a.Equal(t, uint(3), counts.Failed)
|
||||||
|
|
||||||
errorsMap := map[string]string{}
|
errorsMap := map[string]string{}
|
||||||
for _, status := range progress.GetFailedMessages() {
|
for _, status := range progress.GetFailedMessages() {
|
||||||
|
|||||||
@ -82,8 +82,6 @@ func (p *EMLProvider) getFilePathsPerFolder(rules transferRules) (map[string][]s
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *EMLProvider) exportMessages(rule *Rule, filePaths []string, progress *Progress, ch chan<- Message) {
|
func (p *EMLProvider) exportMessages(rule *Rule, filePaths []string, progress *Progress, ch chan<- Message) {
|
||||||
count := uint(len(filePaths))
|
|
||||||
|
|
||||||
for _, filePath := range filePaths {
|
for _, filePath := range filePaths {
|
||||||
if progress.shouldStop() {
|
if progress.shouldStop() {
|
||||||
break
|
break
|
||||||
@ -91,6 +89,8 @@ func (p *EMLProvider) exportMessages(rule *Rule, filePaths []string, progress *P
|
|||||||
|
|
||||||
msg, err := p.exportMessage(rule, filePath)
|
msg, err := p.exportMessage(rule, filePath)
|
||||||
|
|
||||||
|
progress.addMessage(filePath, msg.sourceNames(), msg.targetNames())
|
||||||
|
|
||||||
// Read and check time in body only if the rule specifies it
|
// Read and check time in body only if the rule specifies it
|
||||||
// to not waste energy.
|
// to not waste energy.
|
||||||
if err == nil && rule.HasTimeLimit() {
|
if err == nil && rule.HasTimeLimit() {
|
||||||
@ -99,17 +99,11 @@ func (p *EMLProvider) exportMessages(rule *Rule, filePaths []string, progress *P
|
|||||||
err = msgTimeErr
|
err = msgTimeErr
|
||||||
} else if !rule.isTimeInRange(msgTime) {
|
} else if !rule.isTimeInRange(msgTime) {
|
||||||
log.WithField("msg", filePath).Debug("Message skipped due to time")
|
log.WithField("msg", filePath).Debug("Message skipped due to time")
|
||||||
|
progress.messageSkipped(filePath)
|
||||||
count--
|
|
||||||
progress.updateCount(rule.SourceMailbox.Name, count)
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// addMessage is called after time check to not report message
|
|
||||||
// which should not be exported but any error from reading body
|
|
||||||
// or parsing time is reported as an error.
|
|
||||||
progress.addMessage(filePath, msg.sourceNames(), msg.targetNames())
|
|
||||||
progress.messageExported(filePath, msg.Body, err)
|
progress.messageExported(filePath, msg.Body, err)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
ch <- msg
|
ch <- msg
|
||||||
|
|||||||
@ -114,7 +114,6 @@ func (p *MBOXProvider) transferTo(rules transferRules, progress *Progress, ch ch
|
|||||||
}
|
}
|
||||||
|
|
||||||
index := 0
|
index := 0
|
||||||
count := 0
|
|
||||||
for {
|
for {
|
||||||
if progress.shouldStop() {
|
if progress.shouldStop() {
|
||||||
break
|
break
|
||||||
@ -133,24 +132,18 @@ func (p *MBOXProvider) transferTo(rules transferRules, progress *Progress, ch ch
|
|||||||
|
|
||||||
msg, err := p.exportMessage(rules, folderName, id, msgReader)
|
msg, err := p.exportMessage(rules, folderName, id, msgReader)
|
||||||
|
|
||||||
|
progress.addMessage(id, msg.sourceNames(), msg.targetNames())
|
||||||
|
|
||||||
if err == nil && len(msg.Targets) == 0 {
|
if err == nil && len(msg.Targets) == 0 {
|
||||||
// Here should be called progress.messageSkipped(id) once we have
|
progress.messageSkipped(id)
|
||||||
// this feature, and following progress.updateCount can be removed.
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
count++
|
|
||||||
|
|
||||||
// addMessage is called after time check to not report message
|
|
||||||
// which should not be exported but any error from reading body
|
|
||||||
// or parsing time is reported as an error.
|
|
||||||
progress.addMessage(id, msg.sourceNames(), msg.targetNames())
|
|
||||||
progress.messageExported(id, msg.Body, err)
|
progress.messageExported(id, msg.Body, err)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
ch <- msg
|
ch <- msg
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
progress.updateCount(filePath, uint(count))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *MBOXProvider) exportMessage(rules transferRules, folderName, id string, msgReader io.Reader) (Message, error) {
|
func (p *MBOXProvider) exportMessage(rules transferRules, folderName, id string, msgReader io.Reader) (Message, error) {
|
||||||
@ -177,7 +170,7 @@ func (p *MBOXProvider) getMessageRules(rules transferRules, folderName, id strin
|
|||||||
folderRule, err := rules.getRuleBySourceMailboxName(folderName)
|
folderRule, err := rules.getRuleBySourceMailboxName(folderName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithField("msg", id).WithField("source", folderName).Debug("Message source doesn't have a rule")
|
log.WithField("msg", id).WithField("source", folderName).Debug("Message source doesn't have a rule")
|
||||||
} else {
|
} else if folderRule.Active {
|
||||||
msgRules = append(msgRules, folderRule)
|
msgRules = append(msgRules, folderRule)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -191,7 +184,9 @@ func (p *MBOXProvider) getMessageRules(rules transferRules, folderName, id strin
|
|||||||
log.WithField("msg", id).WithField("source", label).Debug("Message source doesn't have a rule")
|
log.WithField("msg", id).WithField("source", label).Debug("Message source doesn't have a rule")
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
msgRules = append(msgRules, rule)
|
if rule.Active {
|
||||||
|
msgRules = append(msgRules, rule)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -155,6 +155,29 @@ func TestMBOXProviderTransferFromTo(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestMBOXProviderGetMessageRules(t *testing.T) {
|
||||||
|
provider := newTestMBOXProvider("")
|
||||||
|
|
||||||
|
body := []byte(`Subject: Test
|
||||||
|
X-Gmail-Labels: foo,bar
|
||||||
|
|
||||||
|
`)
|
||||||
|
rules := transferRules{
|
||||||
|
rules: map[string]*Rule{
|
||||||
|
"1": {Active: true, SourceMailbox: Mailbox{Name: "folder"}},
|
||||||
|
"2": {Active: false, SourceMailbox: Mailbox{Name: "foo"}},
|
||||||
|
"3": {Active: true, SourceMailbox: Mailbox{Name: "bar"}},
|
||||||
|
"4": {Active: false, SourceMailbox: Mailbox{Name: "baz"}},
|
||||||
|
"5": {Active: true, SourceMailbox: Mailbox{Name: "other"}},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
gotRules := provider.getMessageRules(rules, "folder", "id", body)
|
||||||
|
r.Equal(t, 2, len(gotRules))
|
||||||
|
r.Equal(t, "folder", gotRules[0].SourceMailbox.Name)
|
||||||
|
r.Equal(t, "bar", gotRules[1].SourceMailbox.Name)
|
||||||
|
}
|
||||||
|
|
||||||
func TestMBOXProviderGetMessageTargetsReturnsOnlyOneFolder(t *testing.T) {
|
func TestMBOXProviderGetMessageTargetsReturnsOnlyOneFolder(t *testing.T) {
|
||||||
provider := newTestMBOXProvider("")
|
provider := newTestMBOXProvider("")
|
||||||
|
|
||||||
|
|||||||
@ -28,7 +28,7 @@ import (
|
|||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/ProtonMail/proton-bridge/pkg/message/rfc5322"
|
"github.com/ProtonMail/go-rfc5322"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@ -5,11 +5,12 @@
|
|||||||
package mocks
|
package mocks
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
reflect "reflect"
|
||||||
|
|
||||||
store "github.com/ProtonMail/proton-bridge/internal/store"
|
store "github.com/ProtonMail/proton-bridge/internal/store"
|
||||||
credentials "github.com/ProtonMail/proton-bridge/internal/users/credentials"
|
credentials "github.com/ProtonMail/proton-bridge/internal/users/credentials"
|
||||||
pmapi "github.com/ProtonMail/proton-bridge/pkg/pmapi"
|
pmapi "github.com/ProtonMail/proton-bridge/pkg/pmapi"
|
||||||
gomock "github.com/golang/mock/gomock"
|
gomock "github.com/golang/mock/gomock"
|
||||||
reflect "reflect"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// MockConfiger is a mock of Configer interface
|
// MockConfiger is a mock of Configer interface
|
||||||
|
|||||||
@ -437,7 +437,7 @@ func (u *User) SwitchAddressMode() (err error) {
|
|||||||
|
|
||||||
u.lock.Lock()
|
u.lock.Lock()
|
||||||
defer u.lock.Unlock()
|
defer u.lock.Unlock()
|
||||||
u.closeAllConnections()
|
u.CloseAllConnections()
|
||||||
|
|
||||||
if u.store == nil {
|
if u.store == nil {
|
||||||
err = errors.New("store is not initialised")
|
err = errors.New("store is not initialised")
|
||||||
@ -509,7 +509,7 @@ func (u *User) Logout() (err error) {
|
|||||||
// Do not close whole store, just event loop. Some information might be needed offline (e.g. addressID)
|
// Do not close whole store, just event loop. Some information might be needed offline (e.g. addressID)
|
||||||
u.closeEventLoop()
|
u.closeEventLoop()
|
||||||
|
|
||||||
u.closeAllConnections()
|
u.CloseAllConnections()
|
||||||
|
|
||||||
runtime.GC()
|
runtime.GC()
|
||||||
|
|
||||||
@ -532,8 +532,8 @@ func (u *User) closeEventLoop() {
|
|||||||
u.store.CloseEventLoop()
|
u.store.CloseEventLoop()
|
||||||
}
|
}
|
||||||
|
|
||||||
// closeAllConnections calls CloseConnection for all users addresses.
|
// CloseAllConnections calls CloseConnection for all users addresses.
|
||||||
func (u *User) closeAllConnections() {
|
func (u *User) CloseAllConnections() {
|
||||||
for _, address := range u.creds.EmailList() {
|
for _, address := range u.creds.EmailList() {
|
||||||
u.CloseConnection(address)
|
u.CloseConnection(address)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -186,7 +186,7 @@ func (u *Users) watchAPIAuths() {
|
|||||||
|
|
||||||
func (u *Users) closeAllConnections() {
|
func (u *Users) closeAllConnections() {
|
||||||
for _, user := range u.users {
|
for _, user := range u.users {
|
||||||
user.closeAllConnections()
|
user.CloseAllConnections()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -15,6 +15,13 @@
|
|||||||
// 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 ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
// along with ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
package rfc5322
|
package message
|
||||||
|
|
||||||
//go:generate make antlr
|
import (
|
||||||
|
"github.com/ProtonMail/go-rfc5322"
|
||||||
|
pmmime "github.com/ProtonMail/proton-bridge/pkg/mime"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() { // nolint[noinit]
|
||||||
|
rfc5322.CharsetReader = pmmime.CharsetReader
|
||||||
|
}
|
||||||
@ -26,8 +26,8 @@ import (
|
|||||||
"net/textproto"
|
"net/textproto"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/ProtonMail/go-rfc5322"
|
||||||
"github.com/ProtonMail/proton-bridge/pkg/message/parser"
|
"github.com/ProtonMail/proton-bridge/pkg/message/parser"
|
||||||
"github.com/ProtonMail/proton-bridge/pkg/message/rfc5322"
|
|
||||||
pmmime "github.com/ProtonMail/proton-bridge/pkg/mime"
|
pmmime "github.com/ProtonMail/proton-bridge/pkg/mime"
|
||||||
"github.com/ProtonMail/proton-bridge/pkg/pmapi"
|
"github.com/ProtonMail/proton-bridge/pkg/pmapi"
|
||||||
"github.com/emersion/go-message"
|
"github.com/emersion/go-message"
|
||||||
|
|||||||
@ -1,2 +0,0 @@
|
|||||||
antlr: RFC5322Parser.g4 RFC5322Lexer.g4
|
|
||||||
antlr4 -Dlanguage=Go -o parser $^
|
|
||||||
@ -1,160 +0,0 @@
|
|||||||
# Outline
|
|
||||||
The `rfc5322` package implements a parser for `address-list` and `date-time` strings, as defined in RFC5322.
|
|
||||||
It also supports encoded words (RFC2047) and has international tokens (RFC6532).
|
|
||||||
|
|
||||||
# `rfc5322/parser` directory
|
|
||||||
The lexer and parser are generated using ANTLR4.
|
|
||||||
The grammar is defined in the g4 files:
|
|
||||||
- RFC5322Parser.g4 defines the parser grammar,
|
|
||||||
- RFC5322Lexer.g4 defines the lexer grammar.
|
|
||||||
|
|
||||||
These grammars are derived from the ABNF grammar provided in the RFCs above,
|
|
||||||
albeit with some relaxations added to support "nonstandard" (bad) input.
|
|
||||||
|
|
||||||
Running `antlr4` on these g4 files generates a parser which recognises strings conforming to the grammar:
|
|
||||||
- rfc5322_lexer.go
|
|
||||||
- rfc5322parser_base_listener.go
|
|
||||||
- rfc5322_parser.go
|
|
||||||
- rfc5322parser_listener.go
|
|
||||||
|
|
||||||
The generated parser can then be used to convert a valid address/date into an abstract syntax tree.
|
|
||||||
|
|
||||||
# `rfc5322` directory
|
|
||||||
Once we have an abstract syntax tree, we must turn it into something usable, namely a `mail.Address` or `time.Time`.
|
|
||||||
|
|
||||||
The generated code in the `rfc5322/parser` directory implements a walker.
|
|
||||||
This walker walks over the abstract syntax tree,
|
|
||||||
calling a callback when entering and another when when exiting each node.
|
|
||||||
By default, the callbacks are no-ops, unless they are overridden.
|
|
||||||
|
|
||||||
## `walker.go`
|
|
||||||
The `walker` type extends the base walker, overriding the default no-op callbacks
|
|
||||||
to do something specific when entering and exiting certain nodes.
|
|
||||||
|
|
||||||
The goal of the walker is to traverse the syntax tree, picking out relevant information from each node's text.
|
|
||||||
For example, when parsing a `mailbox` node, the relevant information to pick out from the parse tree is the
|
|
||||||
name and address of the mailbox. This information can appear in a number of different ways, e.g. it might be
|
|
||||||
RFC2047 word-encoded, it might be a string with escaped chars that need to be handled, it might have comments
|
|
||||||
that should be ignored, and so on.
|
|
||||||
|
|
||||||
So while walking the syntax tree, each node needs to ask its children what their "value" is.
|
|
||||||
The `mailbox` needs to ask its child nodes (either a `nameAddr` node or an `addrSpec` node)
|
|
||||||
what the name and address are.
|
|
||||||
If the child node is a `nameAddr`, it needs to ask its `displayName` child what the name is
|
|
||||||
and the `angleAddr` what the address is; these in turn ask `word` nodes, `addrSpec` nodes, etc.
|
|
||||||
|
|
||||||
Each child node is responsible for telling its parent what its own value is.
|
|
||||||
The parent is responsible for assembling the children into something useful.
|
|
||||||
|
|
||||||
Ideally, this would be done with the visitor pattern. But unfortunately, the generated parser only
|
|
||||||
provides a walker interface. So we need to make use of a stack, pushing on nodes when we enter them
|
|
||||||
and popping off nodes when we exit them, to turn the walker into a kind of visitor.
|
|
||||||
|
|
||||||
## `parser.go`
|
|
||||||
This file implements two methods,
|
|
||||||
`ParseAddressList(string) ([]*mail.Address, error)`
|
|
||||||
and
|
|
||||||
`ParseDateTime(string) (time.Time, error)`.
|
|
||||||
|
|
||||||
These methods set up a parser from the raw input, start the walker, and convert the walker result
|
|
||||||
into an object of the correct type.
|
|
||||||
|
|
||||||
|
|
||||||
# Example: Parsing `dateTime`
|
|
||||||
Parsing a date-time is rather simple. The implementation begins in `date_time.go`. The abridged code is below:
|
|
||||||
|
|
||||||
```
|
|
||||||
type dateTime struct {
|
|
||||||
year int
|
|
||||||
...
|
|
||||||
}
|
|
||||||
|
|
||||||
func (dt *dateTime) withYear(year *year) {
|
|
||||||
dt.year = year.value
|
|
||||||
}
|
|
||||||
|
|
||||||
...
|
|
||||||
|
|
||||||
func (w *walker) EnterDateTime(ctx *parser.DateTimeContext) {
|
|
||||||
w.enter(&dateTime{
|
|
||||||
loc: time.UTC,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) ExitDateTime(ctx *parser.DateTimeContext) {
|
|
||||||
dt := w.exit().(*dateTime)
|
|
||||||
w.res = time.Date(dt.year, ...)
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
As you can see, when the walker reaches a `dateTime` node, it pushes a `dateTime` object onto the stack:
|
|
||||||
```
|
|
||||||
w.enter(&dateTime{
|
|
||||||
loc: time.UTC,
|
|
||||||
})
|
|
||||||
```
|
|
||||||
|
|
||||||
and when it leaves a `dateTime` node, it pops it off the stack,
|
|
||||||
converting it from `interface{}` to the concrete type,
|
|
||||||
and uses the parsed `dateTime` values like day, month, year etc
|
|
||||||
to construct a go `time.Time` object to set the walker result:
|
|
||||||
```
|
|
||||||
dt := w.exit().(*dateTime)
|
|
||||||
w.res = time.Date(dt.year, ...)
|
|
||||||
```
|
|
||||||
|
|
||||||
These parsed values were discovered while the walker continued to walk across the date-time node.
|
|
||||||
|
|
||||||
Let's see how the walker discovers the `year`.
|
|
||||||
Here is the abridged code of what happens when the walker enters a `year` node:
|
|
||||||
```
|
|
||||||
type year struct {
|
|
||||||
value int
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) EnterYear(ctx *parser.YearContext) {
|
|
||||||
var text string
|
|
||||||
|
|
||||||
for _, digit := range ctx.AllDigit() {
|
|
||||||
text += digit.GetText()
|
|
||||||
}
|
|
||||||
|
|
||||||
val, err := strconv.Atoi(text)
|
|
||||||
if err != nil {
|
|
||||||
w.err = err
|
|
||||||
}
|
|
||||||
|
|
||||||
w.enter(&year{
|
|
||||||
value: val,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
When entering the `year` node, it collects all the raw digits, which are strings, then
|
|
||||||
converts them to an integer, and sets that as the year's integer value while pushing it onto the stack.
|
|
||||||
|
|
||||||
When exiting, it pops the year off the stack and gives itself to the parent (now on the top of the stack).
|
|
||||||
It doesn't know what type of object the parent is, it just checks to see if anything above it on the stack
|
|
||||||
is expecting a `year` node:
|
|
||||||
```
|
|
||||||
func (w *walker) ExitYear(ctx *parser.YearContext) {
|
|
||||||
type withYear interface {
|
|
||||||
withYear(*year)
|
|
||||||
}
|
|
||||||
|
|
||||||
res := w.exit().(*year)
|
|
||||||
|
|
||||||
if parent, ok := w.parent().(withYear); ok {
|
|
||||||
parent.withYear(res)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
In our case, the `date` is expecting a `year` node because it implements `withYear`,
|
|
||||||
```
|
|
||||||
func (dt *dateTime) withYear(year *year) {
|
|
||||||
dt.year = year.value
|
|
||||||
}
|
|
||||||
```
|
|
||||||
and that is how the `dateTime` data members are collected.
|
|
||||||
|
|
||||||
@ -1,98 +0,0 @@
|
|||||||
// Copyright (c) 2020 Proton Technologies AG
|
|
||||||
//
|
|
||||||
// This file is part of ProtonMail Bridge.
|
|
||||||
//
|
|
||||||
// ProtonMail 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.
|
|
||||||
//
|
|
||||||
// ProtonMail 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 ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
lexer grammar RFC5322Lexer;
|
|
||||||
|
|
||||||
U_00: '\u0000';
|
|
||||||
U_01_08: '\u0001'..'\u0008';
|
|
||||||
TAB: '\t'; // \u0009
|
|
||||||
LF: '\n'; // \u000A
|
|
||||||
U_0B: '\u000B';
|
|
||||||
U_0C: '\u000C';
|
|
||||||
CR: '\r'; // \u000D
|
|
||||||
U_0E_1F: '\u000E'..'\u001F';
|
|
||||||
|
|
||||||
// Printable (0x20-0x7E)
|
|
||||||
SP: ' '; // \u0020
|
|
||||||
Exclamation: '!'; // \u0021
|
|
||||||
DQuote: '"'; // \u0022
|
|
||||||
Hash: '#'; // \u0023
|
|
||||||
Dollar: '$'; // \u0024
|
|
||||||
Percent: '%'; // \u0025
|
|
||||||
Ampersand: '&'; // \u0026
|
|
||||||
SQuote: '\''; // \u0027
|
|
||||||
LParens: '('; // \u0028
|
|
||||||
RParens: ')'; // \u0029
|
|
||||||
Asterisk: '*'; // \u002A
|
|
||||||
Plus: '+'; // \u002B
|
|
||||||
Comma: ','; // \u002C
|
|
||||||
Minus: '-'; // \u002D
|
|
||||||
Period: '.'; // \u002E
|
|
||||||
Slash: '/'; // \u002F
|
|
||||||
Digit: [0-9]; // \u0030 -- \u0039
|
|
||||||
Colon: ':'; // \u003A
|
|
||||||
Semicolon: ';'; // \u003B
|
|
||||||
Less: '<'; // \u003C
|
|
||||||
Equal: '='; // \u003D
|
|
||||||
Greater: '>'; // \u003E
|
|
||||||
Question: '?'; // \u003F
|
|
||||||
At: '@'; // \u0040
|
|
||||||
// alphaUpper
|
|
||||||
LBracket: '['; // \u005B
|
|
||||||
Backslash: '\\'; // \u005C
|
|
||||||
RBracket: ']'; // \u005D
|
|
||||||
Caret: '^'; // \u005E
|
|
||||||
Underscore: '_'; // \u005F
|
|
||||||
Backtick: '`'; // \u0060
|
|
||||||
// alphaLower
|
|
||||||
LCurly: '{'; // \u007B
|
|
||||||
Pipe: '|'; // \u007C
|
|
||||||
RCurly: '}'; // \u007D
|
|
||||||
Tilde: '~'; // \u007E
|
|
||||||
|
|
||||||
// Other
|
|
||||||
Delete: '\u007F';
|
|
||||||
|
|
||||||
// RFC6532 Extension
|
|
||||||
UTF8NonAscii: '\u0080'..'\uFFFF';
|
|
||||||
|
|
||||||
A: 'A'|'a';
|
|
||||||
B: 'B'|'b';
|
|
||||||
C: 'C'|'c';
|
|
||||||
D: 'D'|'d';
|
|
||||||
E: 'E'|'e';
|
|
||||||
F: 'F'|'f';
|
|
||||||
G: 'G'|'g';
|
|
||||||
H: 'H'|'h';
|
|
||||||
I: 'I'|'i';
|
|
||||||
J: 'J'|'j';
|
|
||||||
K: 'K'|'k';
|
|
||||||
L: 'L'|'l';
|
|
||||||
M: 'M'|'m';
|
|
||||||
N: 'N'|'n';
|
|
||||||
O: 'O'|'o';
|
|
||||||
P: 'P'|'p';
|
|
||||||
Q: 'Q'|'q';
|
|
||||||
R: 'R'|'r';
|
|
||||||
S: 'S'|'s';
|
|
||||||
T: 'T'|'t';
|
|
||||||
U: 'U'|'u';
|
|
||||||
V: 'V'|'v';
|
|
||||||
W: 'W'|'w';
|
|
||||||
X: 'X'|'x';
|
|
||||||
Y: 'Y'|'y';
|
|
||||||
Z: 'Z'|'z';
|
|
||||||
@ -1,530 +0,0 @@
|
|||||||
// Copyright (c) 2020 Proton Technologies AG
|
|
||||||
//
|
|
||||||
// This file is part of ProtonMail Bridge.
|
|
||||||
//
|
|
||||||
// ProtonMail 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.
|
|
||||||
//
|
|
||||||
// ProtonMail 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 ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
parser grammar RFC5322Parser;
|
|
||||||
|
|
||||||
options { tokenVocab=RFC5322Lexer; }
|
|
||||||
|
|
||||||
|
|
||||||
// -------------------
|
|
||||||
// 3.2. Lexical tokens
|
|
||||||
// -------------------
|
|
||||||
|
|
||||||
quotedChar: vchar | wsp;
|
|
||||||
|
|
||||||
quotedPair
|
|
||||||
: Backslash quotedChar
|
|
||||||
| obsQP
|
|
||||||
;
|
|
||||||
|
|
||||||
fws
|
|
||||||
: (wsp* crlf)? wsp+
|
|
||||||
| obsFWS
|
|
||||||
;
|
|
||||||
|
|
||||||
ctext
|
|
||||||
: alpha
|
|
||||||
| Exclamation
|
|
||||||
| DQuote
|
|
||||||
| Hash
|
|
||||||
| Dollar
|
|
||||||
| Percent
|
|
||||||
| Ampersand
|
|
||||||
| SQuote
|
|
||||||
| Asterisk
|
|
||||||
| Plus
|
|
||||||
| Comma
|
|
||||||
| Minus
|
|
||||||
| Period
|
|
||||||
| Slash
|
|
||||||
| Digit
|
|
||||||
| Colon
|
|
||||||
| Semicolon
|
|
||||||
| Less
|
|
||||||
| Equal
|
|
||||||
| Greater
|
|
||||||
| Question
|
|
||||||
| At
|
|
||||||
| LBracket
|
|
||||||
| RBracket
|
|
||||||
| Caret
|
|
||||||
| Underscore
|
|
||||||
| Backtick
|
|
||||||
| LCurly
|
|
||||||
| Pipe
|
|
||||||
| RCurly
|
|
||||||
| Tilde
|
|
||||||
| obsCtext
|
|
||||||
| UTF8NonAscii
|
|
||||||
;
|
|
||||||
|
|
||||||
ccontent
|
|
||||||
: ctext
|
|
||||||
| quotedPair
|
|
||||||
| comment
|
|
||||||
;
|
|
||||||
|
|
||||||
comment: LParens (fws? ccontent)* fws? RParens;
|
|
||||||
|
|
||||||
cfws
|
|
||||||
: (fws? comment)+ fws?
|
|
||||||
| fws
|
|
||||||
;
|
|
||||||
|
|
||||||
atext
|
|
||||||
: alpha
|
|
||||||
| Digit
|
|
||||||
| Exclamation
|
|
||||||
| Hash
|
|
||||||
| Dollar
|
|
||||||
| Percent
|
|
||||||
| Ampersand
|
|
||||||
| SQuote
|
|
||||||
| Asterisk
|
|
||||||
| Plus
|
|
||||||
| Minus
|
|
||||||
| Slash
|
|
||||||
| Equal
|
|
||||||
| Question
|
|
||||||
| Caret
|
|
||||||
| Underscore
|
|
||||||
| Backtick
|
|
||||||
| LCurly
|
|
||||||
| Pipe
|
|
||||||
| RCurly
|
|
||||||
| Tilde
|
|
||||||
| UTF8NonAscii
|
|
||||||
;
|
|
||||||
|
|
||||||
atom: atext+;
|
|
||||||
|
|
||||||
// Allow dotAtom to have a trailing period; some messages in the wild look like this.
|
|
||||||
dotAtom: atext+ (Period atext+)* Period?;
|
|
||||||
|
|
||||||
qtext
|
|
||||||
: alpha
|
|
||||||
| Exclamation
|
|
||||||
| Hash
|
|
||||||
| Dollar
|
|
||||||
| Percent
|
|
||||||
| Ampersand
|
|
||||||
| SQuote
|
|
||||||
| LParens
|
|
||||||
| RParens
|
|
||||||
| Asterisk
|
|
||||||
| Plus
|
|
||||||
| Comma
|
|
||||||
| Minus
|
|
||||||
| Period
|
|
||||||
| Slash
|
|
||||||
| Digit
|
|
||||||
| Colon
|
|
||||||
| Semicolon
|
|
||||||
| Less
|
|
||||||
| Equal
|
|
||||||
| Greater
|
|
||||||
| Question
|
|
||||||
| At
|
|
||||||
| LBracket
|
|
||||||
| RBracket
|
|
||||||
| Caret
|
|
||||||
| Underscore
|
|
||||||
| Backtick
|
|
||||||
| LCurly
|
|
||||||
| Pipe
|
|
||||||
| RCurly
|
|
||||||
| Tilde
|
|
||||||
| obsQtext
|
|
||||||
| UTF8NonAscii
|
|
||||||
;
|
|
||||||
|
|
||||||
quotedContent
|
|
||||||
: qtext
|
|
||||||
| quotedPair
|
|
||||||
;
|
|
||||||
|
|
||||||
quotedValue: (fws? quotedContent)*;
|
|
||||||
|
|
||||||
quotedString: DQuote quotedValue fws? DQuote;
|
|
||||||
|
|
||||||
// Allow word to consist of the @ token.
|
|
||||||
word
|
|
||||||
: cfws? encodedWord cfws?
|
|
||||||
| cfws? atom cfws?
|
|
||||||
| cfws? quotedString cfws?
|
|
||||||
| At
|
|
||||||
;
|
|
||||||
|
|
||||||
|
|
||||||
// --------------------------------
|
|
||||||
// 3.3. Date and Time Specification
|
|
||||||
// --------------------------------
|
|
||||||
|
|
||||||
dateTime: (dayOfweek Comma)? day month year hour Colon minute (Colon second)? zone? cfws? EOF;
|
|
||||||
|
|
||||||
dayOfweek
|
|
||||||
: fws? dayName
|
|
||||||
| cfws? dayName cfws?
|
|
||||||
;
|
|
||||||
|
|
||||||
dayName
|
|
||||||
: M O N
|
|
||||||
| T U E
|
|
||||||
| W E D
|
|
||||||
| T H U
|
|
||||||
| F R I
|
|
||||||
| S A T
|
|
||||||
| S U N
|
|
||||||
;
|
|
||||||
|
|
||||||
day
|
|
||||||
: fws? Digit Digit? fws
|
|
||||||
| cfws? Digit Digit? cfws?
|
|
||||||
;
|
|
||||||
|
|
||||||
month
|
|
||||||
: J A N
|
|
||||||
| F E B
|
|
||||||
| M A R
|
|
||||||
| A P R
|
|
||||||
| M A Y
|
|
||||||
| J U N
|
|
||||||
| J U L
|
|
||||||
| A U G
|
|
||||||
| S E P
|
|
||||||
| O C T
|
|
||||||
| N O V
|
|
||||||
| D E C
|
|
||||||
;
|
|
||||||
|
|
||||||
year
|
|
||||||
: fws Digit Digit Digit Digit fws
|
|
||||||
| cfws? Digit Digit cfws?
|
|
||||||
;
|
|
||||||
|
|
||||||
// NOTE: RFC5322 requires two digits for the hour, but we
|
|
||||||
// relax that requirement a bit, allowing single digits.
|
|
||||||
hour
|
|
||||||
: Digit? Digit
|
|
||||||
| cfws? Digit? Digit cfws?
|
|
||||||
;
|
|
||||||
|
|
||||||
minute
|
|
||||||
: Digit Digit
|
|
||||||
| cfws? Digit Digit cfws?
|
|
||||||
;
|
|
||||||
|
|
||||||
second
|
|
||||||
: Digit Digit
|
|
||||||
| cfws? Digit Digit cfws?
|
|
||||||
;
|
|
||||||
|
|
||||||
offset: (Plus | Minus)? Digit Digit Digit Digit;
|
|
||||||
|
|
||||||
zone
|
|
||||||
: fws offset
|
|
||||||
| obsZone
|
|
||||||
;
|
|
||||||
|
|
||||||
|
|
||||||
// --------------------------
|
|
||||||
// 3.4. Address Specification
|
|
||||||
// --------------------------
|
|
||||||
|
|
||||||
address
|
|
||||||
: mailbox
|
|
||||||
| group
|
|
||||||
;
|
|
||||||
|
|
||||||
mailbox
|
|
||||||
: nameAddr
|
|
||||||
| addrSpec
|
|
||||||
;
|
|
||||||
|
|
||||||
nameAddr: displayName? angleAddr;
|
|
||||||
|
|
||||||
angleAddr
|
|
||||||
: cfws? Less addrSpec? Greater cfws?
|
|
||||||
| obsAngleAddr
|
|
||||||
;
|
|
||||||
|
|
||||||
group: displayName Colon groupList? Semicolon cfws?;
|
|
||||||
|
|
||||||
displayName
|
|
||||||
: word+
|
|
||||||
| word (word | Period | cfws)*
|
|
||||||
;
|
|
||||||
|
|
||||||
mailboxList
|
|
||||||
: mailbox (Comma mailbox)*
|
|
||||||
| obsMboxList
|
|
||||||
;
|
|
||||||
|
|
||||||
addressList
|
|
||||||
: address (Comma address)* EOF
|
|
||||||
| obsAddrList EOF
|
|
||||||
;
|
|
||||||
|
|
||||||
groupList
|
|
||||||
: mailboxList
|
|
||||||
| cfws
|
|
||||||
| obsGroupList
|
|
||||||
;
|
|
||||||
|
|
||||||
// Allow addrSpec contain a port.
|
|
||||||
addrSpec: localPart At domain (Colon port)?;
|
|
||||||
|
|
||||||
localPart
|
|
||||||
: cfws? dotAtom cfws?
|
|
||||||
| cfws? quotedString cfws?
|
|
||||||
| obsLocalPart
|
|
||||||
;
|
|
||||||
|
|
||||||
port: Digit+;
|
|
||||||
|
|
||||||
domain
|
|
||||||
: cfws? dotAtom cfws?
|
|
||||||
| cfws? domainLiteral cfws?
|
|
||||||
| cfws? obsDomain cfws?
|
|
||||||
;
|
|
||||||
|
|
||||||
domainLiteral: LBracket (fws? dtext)* fws? RBracket;
|
|
||||||
|
|
||||||
dtext
|
|
||||||
: alpha
|
|
||||||
| Exclamation
|
|
||||||
| DQuote
|
|
||||||
| Hash
|
|
||||||
| Dollar
|
|
||||||
| Percent
|
|
||||||
| Ampersand
|
|
||||||
| SQuote
|
|
||||||
| LParens
|
|
||||||
| RParens
|
|
||||||
| Asterisk
|
|
||||||
| Plus
|
|
||||||
| Comma
|
|
||||||
| Minus
|
|
||||||
| Period
|
|
||||||
| Slash
|
|
||||||
| Digit
|
|
||||||
| Colon
|
|
||||||
| Semicolon
|
|
||||||
| Less
|
|
||||||
| Equal
|
|
||||||
| Greater
|
|
||||||
| Question
|
|
||||||
| At
|
|
||||||
| Caret
|
|
||||||
| Underscore
|
|
||||||
| Backtick
|
|
||||||
| LCurly
|
|
||||||
| Pipe
|
|
||||||
| RCurly
|
|
||||||
| Tilde
|
|
||||||
//| obsDtext
|
|
||||||
| UTF8NonAscii
|
|
||||||
;
|
|
||||||
|
|
||||||
|
|
||||||
// ----------------------------------
|
|
||||||
// 4.1. Miscellaneous Obsolete Tokens
|
|
||||||
// ----------------------------------
|
|
||||||
|
|
||||||
obsNoWSCTL
|
|
||||||
: U_01_08
|
|
||||||
| U_0B
|
|
||||||
| U_0C
|
|
||||||
| U_0E_1F
|
|
||||||
| Delete
|
|
||||||
;
|
|
||||||
|
|
||||||
obsCtext: obsNoWSCTL;
|
|
||||||
|
|
||||||
obsQtext: obsNoWSCTL;
|
|
||||||
|
|
||||||
obsQP: Backslash (U_00 | obsNoWSCTL | LF | CR);
|
|
||||||
|
|
||||||
|
|
||||||
// ---------------------------------
|
|
||||||
// 4.2. Obsolete Folding White Space
|
|
||||||
// ---------------------------------
|
|
||||||
|
|
||||||
obsFWS: wsp+ (crlf wsp+);
|
|
||||||
|
|
||||||
|
|
||||||
// ---------------------------
|
|
||||||
// 4.3. Obsolete Date and Time
|
|
||||||
// ---------------------------
|
|
||||||
|
|
||||||
obsZone
|
|
||||||
: U T
|
|
||||||
| U T C
|
|
||||||
| G M T
|
|
||||||
| E S T
|
|
||||||
| E D T
|
|
||||||
| C S T
|
|
||||||
| C D T
|
|
||||||
| M S T
|
|
||||||
| M D T
|
|
||||||
| P S T
|
|
||||||
| P D T
|
|
||||||
//| obsZoneMilitary
|
|
||||||
;
|
|
||||||
|
|
||||||
|
|
||||||
// ------------------------
|
|
||||||
// 4.4. Obsolete Addressing
|
|
||||||
// ------------------------
|
|
||||||
|
|
||||||
obsAngleAddr: cfws? Less obsRoute addrSpec Greater cfws?;
|
|
||||||
|
|
||||||
obsRoute: obsDomainList Colon;
|
|
||||||
|
|
||||||
obsDomainList: (cfws | Comma)* At domain (Comma cfws? (At domain)?)*;
|
|
||||||
|
|
||||||
obsMboxList: (cfws? Comma)* mailbox (Comma (mailbox | cfws)?)*;
|
|
||||||
|
|
||||||
obsAddrList: (cfws? Comma)* address (Comma (address | cfws)?)*;
|
|
||||||
|
|
||||||
obsGroupList: (cfws? Comma)+ cfws?;
|
|
||||||
|
|
||||||
obsLocalPart: word (Period word)*;
|
|
||||||
|
|
||||||
obsDomain: atom (Period atom)*;
|
|
||||||
|
|
||||||
|
|
||||||
// ------------------------------------
|
|
||||||
// 2. Syntax of encoded-words (RFC2047)
|
|
||||||
// ------------------------------------
|
|
||||||
|
|
||||||
encodedWord: Equal Question charset Question encoding Question encodedText Question Equal;
|
|
||||||
|
|
||||||
charset: token;
|
|
||||||
|
|
||||||
encoding: token;
|
|
||||||
|
|
||||||
token: tokenChar+;
|
|
||||||
|
|
||||||
tokenChar
|
|
||||||
: alpha
|
|
||||||
| Exclamation
|
|
||||||
| Hash
|
|
||||||
| Dollar
|
|
||||||
| Percent
|
|
||||||
| Ampersand
|
|
||||||
| SQuote
|
|
||||||
| Asterisk
|
|
||||||
| Plus
|
|
||||||
| Minus
|
|
||||||
| Digit
|
|
||||||
| Backslash
|
|
||||||
| Caret
|
|
||||||
| Underscore
|
|
||||||
| Backtick
|
|
||||||
| LCurly
|
|
||||||
| Pipe
|
|
||||||
| RCurly
|
|
||||||
| Tilde
|
|
||||||
;
|
|
||||||
|
|
||||||
encodedText: encodedChar+;
|
|
||||||
|
|
||||||
encodedChar
|
|
||||||
: alpha
|
|
||||||
| Exclamation
|
|
||||||
| DQuote
|
|
||||||
| Hash
|
|
||||||
| Dollar
|
|
||||||
| Percent
|
|
||||||
| Ampersand
|
|
||||||
| SQuote
|
|
||||||
| LParens
|
|
||||||
| RParens
|
|
||||||
| Asterisk
|
|
||||||
| Plus
|
|
||||||
| Comma
|
|
||||||
| Minus
|
|
||||||
| Period
|
|
||||||
| Slash
|
|
||||||
| Digit
|
|
||||||
| Colon
|
|
||||||
| Semicolon
|
|
||||||
| Less
|
|
||||||
| Equal
|
|
||||||
| Greater
|
|
||||||
| At
|
|
||||||
| LBracket
|
|
||||||
| Backslash
|
|
||||||
| RBracket
|
|
||||||
| Caret
|
|
||||||
| Underscore
|
|
||||||
| Backtick
|
|
||||||
| LCurly
|
|
||||||
| Pipe
|
|
||||||
| RCurly
|
|
||||||
| Tilde
|
|
||||||
;
|
|
||||||
|
|
||||||
|
|
||||||
// -------------------------
|
|
||||||
// B.1. Core Rules (RFC5234)
|
|
||||||
// -------------------------
|
|
||||||
|
|
||||||
crlf: CR LF;
|
|
||||||
|
|
||||||
wsp: SP | TAB;
|
|
||||||
|
|
||||||
vchar
|
|
||||||
: alpha
|
|
||||||
| Exclamation
|
|
||||||
| DQuote
|
|
||||||
| Hash
|
|
||||||
| Dollar
|
|
||||||
| Percent
|
|
||||||
| Ampersand
|
|
||||||
| SQuote
|
|
||||||
| LParens
|
|
||||||
| RParens
|
|
||||||
| Asterisk
|
|
||||||
| Plus
|
|
||||||
| Comma
|
|
||||||
| Minus
|
|
||||||
| Period
|
|
||||||
| Slash
|
|
||||||
| Digit
|
|
||||||
| Colon
|
|
||||||
| Semicolon
|
|
||||||
| Less
|
|
||||||
| Equal
|
|
||||||
| Greater
|
|
||||||
| Question
|
|
||||||
| At
|
|
||||||
| LBracket
|
|
||||||
| Backslash
|
|
||||||
| RBracket
|
|
||||||
| Caret
|
|
||||||
| Underscore
|
|
||||||
| Backtick
|
|
||||||
| LCurly
|
|
||||||
| Pipe
|
|
||||||
| RCurly
|
|
||||||
| Tilde
|
|
||||||
| UTF8NonAscii
|
|
||||||
;
|
|
||||||
|
|
||||||
alpha: A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Y | Z ;
|
|
||||||
@ -1,58 +0,0 @@
|
|||||||
// Copyright (c) 2020 Proton Technologies AG
|
|
||||||
//
|
|
||||||
// This file is part of ProtonMail Bridge.
|
|
||||||
//
|
|
||||||
// ProtonMail 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.
|
|
||||||
//
|
|
||||||
// ProtonMail 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 ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
package rfc5322
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/ProtonMail/proton-bridge/pkg/message/rfc5322/parser"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
|
||||||
|
|
||||||
type addrSpec struct {
|
|
||||||
localPart, domain string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *addrSpec) withLocalPart(localPart *localPart) {
|
|
||||||
a.localPart = localPart.value
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *addrSpec) withDomain(domain *domain) {
|
|
||||||
a.domain = domain.value
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *addrSpec) withPort(port *port) {
|
|
||||||
a.domain += ":" + port.value
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) EnterAddrSpec(ctx *parser.AddrSpecContext) {
|
|
||||||
logrus.WithField("text", ctx.GetText()).Trace("Entering addrSpec")
|
|
||||||
w.enter(&addrSpec{})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) ExitAddrSpec(ctx *parser.AddrSpecContext) {
|
|
||||||
logrus.WithField("text", ctx.GetText()).Trace("Exiting addrSpec")
|
|
||||||
|
|
||||||
type withAddrSpec interface {
|
|
||||||
withAddrSpec(*addrSpec)
|
|
||||||
}
|
|
||||||
|
|
||||||
res := w.exit().(*addrSpec)
|
|
||||||
|
|
||||||
if parent, ok := w.parent().(withAddrSpec); ok {
|
|
||||||
parent.withAddrSpec(res)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,59 +0,0 @@
|
|||||||
// Copyright (c) 2020 Proton Technologies AG
|
|
||||||
//
|
|
||||||
// This file is part of ProtonMail Bridge.
|
|
||||||
//
|
|
||||||
// ProtonMail 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.
|
|
||||||
//
|
|
||||||
// ProtonMail 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 ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
package rfc5322
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/mail"
|
|
||||||
|
|
||||||
"github.com/ProtonMail/proton-bridge/pkg/message/rfc5322/parser"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
|
||||||
|
|
||||||
type address struct {
|
|
||||||
addresses []*mail.Address
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *address) withMailbox(mailbox *mailbox) {
|
|
||||||
a.addresses = append(a.addresses, &mail.Address{
|
|
||||||
Name: mailbox.name,
|
|
||||||
Address: mailbox.address,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *address) withGroup(group *group) {
|
|
||||||
a.addresses = append(a.addresses, group.addresses...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) EnterAddress(ctx *parser.AddressContext) {
|
|
||||||
logrus.WithField("text", ctx.GetText()).Trace("Entering address")
|
|
||||||
w.enter(&address{})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) ExitAddress(ctx *parser.AddressContext) {
|
|
||||||
logrus.WithField("text", ctx.GetText()).Trace("Exiting address")
|
|
||||||
|
|
||||||
type withAddress interface {
|
|
||||||
withAddress(*address)
|
|
||||||
}
|
|
||||||
|
|
||||||
res := w.exit().(*address)
|
|
||||||
|
|
||||||
if parent, ok := w.parent().(withAddress); ok {
|
|
||||||
parent.withAddress(res)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,43 +0,0 @@
|
|||||||
// Copyright (c) 2020 Proton Technologies AG
|
|
||||||
//
|
|
||||||
// This file is part of ProtonMail Bridge.
|
|
||||||
//
|
|
||||||
// ProtonMail 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.
|
|
||||||
//
|
|
||||||
// ProtonMail 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 ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
package rfc5322
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/mail"
|
|
||||||
|
|
||||||
"github.com/ProtonMail/proton-bridge/pkg/message/rfc5322/parser"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
|
||||||
|
|
||||||
type addressList struct {
|
|
||||||
addresses []*mail.Address
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *addressList) withAddress(address *address) {
|
|
||||||
a.addresses = append(a.addresses, address.addresses...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) EnterAddressList(ctx *parser.AddressListContext) {
|
|
||||||
logrus.WithField("text", ctx.GetText()).Trace("Entering addressList")
|
|
||||||
w.enter(&addressList{})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) ExitAddressList(ctx *parser.AddressListContext) {
|
|
||||||
logrus.WithField("text", ctx.GetText()).Trace("Exiting addressList")
|
|
||||||
w.res = w.exit().(*addressList).addresses
|
|
||||||
}
|
|
||||||
@ -1,56 +0,0 @@
|
|||||||
// Copyright (c) 2020 Proton Technologies AG
|
|
||||||
//
|
|
||||||
// This file is part of ProtonMail Bridge.
|
|
||||||
//
|
|
||||||
// ProtonMail 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.
|
|
||||||
//
|
|
||||||
// ProtonMail 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 ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
package rfc5322
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/ProtonMail/proton-bridge/pkg/message/rfc5322/parser"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
|
||||||
|
|
||||||
type angleAddr struct {
|
|
||||||
address string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *angleAddr) withAddrSpec(addrSpec *addrSpec) {
|
|
||||||
a.address = fmt.Sprintf("%v@%v", addrSpec.localPart, addrSpec.domain)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *angleAddr) withObsAngleAddr(obsAngleAddr *obsAngleAddr) {
|
|
||||||
a.address = obsAngleAddr.address
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) EnterAngleAddr(ctx *parser.AngleAddrContext) {
|
|
||||||
logrus.WithField("text", ctx.GetText()).Trace("Entering angleAddr")
|
|
||||||
w.enter(&angleAddr{})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) ExitAngleAddr(ctx *parser.AngleAddrContext) {
|
|
||||||
logrus.WithField("text", ctx.GetText()).Trace("Exiting angleAddr")
|
|
||||||
|
|
||||||
type withAngleAddr interface {
|
|
||||||
withAngleAddr(*angleAddr)
|
|
||||||
}
|
|
||||||
|
|
||||||
res := w.exit().(*angleAddr)
|
|
||||||
|
|
||||||
if parent, ok := w.parent().(withAngleAddr); ok {
|
|
||||||
parent.withAngleAddr(res)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,49 +0,0 @@
|
|||||||
// Copyright (c) 2020 Proton Technologies AG
|
|
||||||
//
|
|
||||||
// This file is part of ProtonMail Bridge.
|
|
||||||
//
|
|
||||||
// ProtonMail 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.
|
|
||||||
//
|
|
||||||
// ProtonMail 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 ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
package rfc5322
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/ProtonMail/proton-bridge/pkg/message/rfc5322/parser"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
|
||||||
|
|
||||||
type atom struct {
|
|
||||||
value string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) EnterAtom(ctx *parser.AtomContext) {
|
|
||||||
logrus.WithField("text", ctx.GetText()).Trace("Entering atom")
|
|
||||||
|
|
||||||
w.enter(&atom{
|
|
||||||
value: ctx.GetText(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) ExitAtom(ctx *parser.AtomContext) {
|
|
||||||
logrus.WithField("text", ctx.GetText()).Trace("Exiting atom")
|
|
||||||
|
|
||||||
type withAtom interface {
|
|
||||||
withAtom(*atom)
|
|
||||||
}
|
|
||||||
|
|
||||||
res := w.exit().(*atom)
|
|
||||||
|
|
||||||
if parent, ok := w.parent().(withAtom); ok {
|
|
||||||
parent.withAtom(res)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,79 +0,0 @@
|
|||||||
// Copyright (c) 2020 Proton Technologies AG
|
|
||||||
//
|
|
||||||
// This file is part of ProtonMail Bridge.
|
|
||||||
//
|
|
||||||
// ProtonMail 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.
|
|
||||||
//
|
|
||||||
// ProtonMail 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 ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
package rfc5322
|
|
||||||
|
|
||||||
import (
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/ProtonMail/proton-bridge/pkg/message/rfc5322/parser"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
|
||||||
|
|
||||||
type dateTime struct {
|
|
||||||
day int
|
|
||||||
month time.Month
|
|
||||||
year int
|
|
||||||
|
|
||||||
hour, min, sec int
|
|
||||||
|
|
||||||
loc *time.Location
|
|
||||||
}
|
|
||||||
|
|
||||||
func (dt *dateTime) withDay(day *day) {
|
|
||||||
dt.day = day.value
|
|
||||||
}
|
|
||||||
|
|
||||||
func (dt *dateTime) withMonth(month *month) {
|
|
||||||
dt.month = month.value
|
|
||||||
}
|
|
||||||
|
|
||||||
func (dt *dateTime) withYear(year *year) {
|
|
||||||
dt.year = year.value
|
|
||||||
}
|
|
||||||
|
|
||||||
func (dt *dateTime) withHour(hour *hour) {
|
|
||||||
dt.hour = hour.value
|
|
||||||
}
|
|
||||||
|
|
||||||
func (dt *dateTime) withMinute(minute *minute) {
|
|
||||||
dt.min = minute.value
|
|
||||||
}
|
|
||||||
|
|
||||||
func (dt *dateTime) withSecond(second *second) {
|
|
||||||
dt.sec = second.value
|
|
||||||
}
|
|
||||||
|
|
||||||
func (dt *dateTime) withZone(zone *zone) {
|
|
||||||
dt.loc = zone.location
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) EnterDateTime(ctx *parser.DateTimeContext) {
|
|
||||||
logrus.WithField("text", ctx.GetText()).Trace("Entering dateTime")
|
|
||||||
|
|
||||||
w.enter(&dateTime{
|
|
||||||
loc: time.UTC,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) ExitDateTime(ctx *parser.DateTimeContext) {
|
|
||||||
logrus.WithField("text", ctx.GetText()).Trace("Exiting dateTime")
|
|
||||||
|
|
||||||
dt := w.exit().(*dateTime)
|
|
||||||
|
|
||||||
w.res = time.Date(dt.year, dt.month, dt.day, dt.hour, dt.min, dt.sec, 0, dt.loc)
|
|
||||||
}
|
|
||||||
@ -1,62 +0,0 @@
|
|||||||
// Copyright (c) 2020 Proton Technologies AG
|
|
||||||
//
|
|
||||||
// This file is part of ProtonMail Bridge.
|
|
||||||
//
|
|
||||||
// ProtonMail 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.
|
|
||||||
//
|
|
||||||
// ProtonMail 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 ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
package rfc5322
|
|
||||||
|
|
||||||
import (
|
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"github.com/ProtonMail/proton-bridge/pkg/message/rfc5322/parser"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
|
||||||
|
|
||||||
type day struct {
|
|
||||||
value int
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) EnterDay(ctx *parser.DayContext) {
|
|
||||||
logrus.WithField("text", ctx.GetText()).Trace("Entering day")
|
|
||||||
|
|
||||||
var text string
|
|
||||||
|
|
||||||
for _, digit := range ctx.AllDigit() {
|
|
||||||
text += digit.GetText()
|
|
||||||
}
|
|
||||||
|
|
||||||
val, err := strconv.Atoi(text)
|
|
||||||
if err != nil {
|
|
||||||
w.err = err
|
|
||||||
}
|
|
||||||
|
|
||||||
w.enter(&day{
|
|
||||||
value: val,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) ExitDay(ctx *parser.DayContext) {
|
|
||||||
logrus.WithField("text", ctx.GetText()).Trace("Exiting day")
|
|
||||||
|
|
||||||
type withDay interface {
|
|
||||||
withDay(*day)
|
|
||||||
}
|
|
||||||
|
|
||||||
res := w.exit().(*day)
|
|
||||||
|
|
||||||
if parent, ok := w.parent().(withDay); ok {
|
|
||||||
parent.withDay(res)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,50 +0,0 @@
|
|||||||
// Copyright (c) 2020 Proton Technologies AG
|
|
||||||
//
|
|
||||||
// This file is part of ProtonMail Bridge.
|
|
||||||
//
|
|
||||||
// ProtonMail 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.
|
|
||||||
//
|
|
||||||
// ProtonMail 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 ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
package rfc5322
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/ProtonMail/proton-bridge/pkg/message/rfc5322/parser"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
|
||||||
|
|
||||||
type displayName struct {
|
|
||||||
words []string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *displayName) withWord(word *word) {
|
|
||||||
n.words = append(n.words, word.value)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) EnterDisplayName(ctx *parser.DisplayNameContext) {
|
|
||||||
logrus.WithField("text", ctx.GetText()).Trace("Entering displayName")
|
|
||||||
w.enter(&displayName{})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) ExitDisplayName(ctx *parser.DisplayNameContext) {
|
|
||||||
logrus.WithField("text", ctx.GetText()).Trace("Exiting displayName")
|
|
||||||
|
|
||||||
type withDisplayName interface {
|
|
||||||
withDisplayName(*displayName)
|
|
||||||
}
|
|
||||||
|
|
||||||
res := w.exit().(*displayName)
|
|
||||||
|
|
||||||
if parent, ok := w.parent().(withDisplayName); ok {
|
|
||||||
parent.withDisplayName(res)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,60 +0,0 @@
|
|||||||
// Copyright (c) 2020 Proton Technologies AG
|
|
||||||
//
|
|
||||||
// This file is part of ProtonMail Bridge.
|
|
||||||
//
|
|
||||||
// ProtonMail 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.
|
|
||||||
//
|
|
||||||
// ProtonMail 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 ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
package rfc5322
|
|
||||||
|
|
||||||
import (
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/ProtonMail/proton-bridge/pkg/message/rfc5322/parser"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
|
||||||
|
|
||||||
type domain struct {
|
|
||||||
value string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *domain) withDotAtom(dotAtom *dotAtom) {
|
|
||||||
d.value = dotAtom.value
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *domain) withDomainLiteral(domainLiteral *domainLiteral) {
|
|
||||||
d.value = domainLiteral.value
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *domain) withObsDomain(obsDomain *obsDomain) {
|
|
||||||
d.value = strings.Join(obsDomain.atoms, ".")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) EnterDomain(ctx *parser.DomainContext) {
|
|
||||||
logrus.WithField("text", ctx.GetText()).Trace("Entering domain")
|
|
||||||
w.enter(&domain{})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) ExitDomain(ctx *parser.DomainContext) {
|
|
||||||
logrus.WithField("text", ctx.GetText()).Trace("Exiting domain")
|
|
||||||
|
|
||||||
type withDomain interface {
|
|
||||||
withDomain(*domain)
|
|
||||||
}
|
|
||||||
|
|
||||||
res := w.exit().(*domain)
|
|
||||||
|
|
||||||
if parent, ok := w.parent().(withDomain); ok {
|
|
||||||
parent.withDomain(res)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,49 +0,0 @@
|
|||||||
// Copyright (c) 2020 Proton Technologies AG
|
|
||||||
//
|
|
||||||
// This file is part of ProtonMail Bridge.
|
|
||||||
//
|
|
||||||
// ProtonMail 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.
|
|
||||||
//
|
|
||||||
// ProtonMail 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 ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
package rfc5322
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/ProtonMail/proton-bridge/pkg/message/rfc5322/parser"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
|
||||||
|
|
||||||
type domainLiteral struct {
|
|
||||||
value string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) EnterDomainLiteral(ctx *parser.DomainLiteralContext) {
|
|
||||||
logrus.WithField("text", ctx.GetText()).Trace("Entering domainLiteral")
|
|
||||||
|
|
||||||
w.enter(&domainLiteral{
|
|
||||||
value: ctx.GetText(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) ExitDomainLiteral(ctx *parser.DomainLiteralContext) {
|
|
||||||
logrus.WithField("text", ctx.GetText()).Trace("Exiting domainLiteral")
|
|
||||||
|
|
||||||
type withDomainLiteral interface {
|
|
||||||
withDomainLiteral(*domainLiteral)
|
|
||||||
}
|
|
||||||
|
|
||||||
res := w.exit().(*domainLiteral)
|
|
||||||
|
|
||||||
if parent, ok := w.parent().(withDomainLiteral); ok {
|
|
||||||
parent.withDomainLiteral(res)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,49 +0,0 @@
|
|||||||
// Copyright (c) 2020 Proton Technologies AG
|
|
||||||
//
|
|
||||||
// This file is part of ProtonMail Bridge.
|
|
||||||
//
|
|
||||||
// ProtonMail 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.
|
|
||||||
//
|
|
||||||
// ProtonMail 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 ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
package rfc5322
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/ProtonMail/proton-bridge/pkg/message/rfc5322/parser"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
|
||||||
|
|
||||||
type dotAtom struct {
|
|
||||||
value string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) EnterDotAtom(ctx *parser.DotAtomContext) {
|
|
||||||
logrus.WithField("text", ctx.GetText()).Trace("Entering dotAtom")
|
|
||||||
|
|
||||||
w.enter(&dotAtom{
|
|
||||||
value: ctx.GetText(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) ExitDotAtom(ctx *parser.DotAtomContext) {
|
|
||||||
logrus.WithField("text", ctx.GetText()).Trace("Exiting dotAtom")
|
|
||||||
|
|
||||||
type withDotAtom interface {
|
|
||||||
withDotAtom(*dotAtom)
|
|
||||||
}
|
|
||||||
|
|
||||||
res := w.exit().(*dotAtom)
|
|
||||||
|
|
||||||
if parent, ok := w.parent().(withDotAtom); ok {
|
|
||||||
parent.withDotAtom(res)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,55 +0,0 @@
|
|||||||
// Copyright (c) 2020 Proton Technologies AG
|
|
||||||
//
|
|
||||||
// This file is part of ProtonMail Bridge.
|
|
||||||
//
|
|
||||||
// ProtonMail 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.
|
|
||||||
//
|
|
||||||
// ProtonMail 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 ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
package rfc5322
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/ProtonMail/proton-bridge/pkg/message/rfc5322/parser"
|
|
||||||
pmmime "github.com/ProtonMail/proton-bridge/pkg/mime"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
|
||||||
|
|
||||||
type encodedWord struct {
|
|
||||||
value string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) EnterEncodedWord(ctx *parser.EncodedWordContext) {
|
|
||||||
logrus.WithField("text", ctx.GetText()).Trace("Entering encodedWord")
|
|
||||||
|
|
||||||
word, err := pmmime.WordDec.Decode(ctx.GetText())
|
|
||||||
if err != nil {
|
|
||||||
word = ctx.GetText()
|
|
||||||
}
|
|
||||||
|
|
||||||
w.enter(&encodedWord{
|
|
||||||
value: word,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) ExitEncodedWord(ctx *parser.EncodedWordContext) {
|
|
||||||
logrus.WithField("text", ctx.GetText()).Trace("Exiting encodedWord")
|
|
||||||
|
|
||||||
type withEncodedWord interface {
|
|
||||||
withEncodedWord(*encodedWord)
|
|
||||||
}
|
|
||||||
|
|
||||||
res := w.exit().(*encodedWord)
|
|
||||||
|
|
||||||
if parent, ok := w.parent().(withEncodedWord); ok {
|
|
||||||
parent.withEncodedWord(res)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,52 +0,0 @@
|
|||||||
// Copyright (c) 2020 Proton Technologies AG
|
|
||||||
//
|
|
||||||
// This file is part of ProtonMail Bridge.
|
|
||||||
//
|
|
||||||
// ProtonMail 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.
|
|
||||||
//
|
|
||||||
// ProtonMail 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 ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
package rfc5322
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/mail"
|
|
||||||
|
|
||||||
"github.com/ProtonMail/proton-bridge/pkg/message/rfc5322/parser"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
|
||||||
|
|
||||||
type group struct {
|
|
||||||
addresses []*mail.Address
|
|
||||||
}
|
|
||||||
|
|
||||||
func (g *group) withGroupList(groupList *groupList) {
|
|
||||||
g.addresses = append(g.addresses, groupList.addresses...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) EnterGroup(ctx *parser.GroupContext) {
|
|
||||||
logrus.WithField("text", ctx.GetText()).Trace("Entering group")
|
|
||||||
w.enter(&group{})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) ExitGroup(ctx *parser.GroupContext) {
|
|
||||||
logrus.WithField("text", ctx.GetText()).Trace("Exiting group")
|
|
||||||
|
|
||||||
type withGroup interface {
|
|
||||||
withGroup(*group)
|
|
||||||
}
|
|
||||||
|
|
||||||
res := w.exit().(*group)
|
|
||||||
|
|
||||||
if parent, ok := w.parent().(withGroup); ok {
|
|
||||||
parent.withGroup(res)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,52 +0,0 @@
|
|||||||
// Copyright (c) 2020 Proton Technologies AG
|
|
||||||
//
|
|
||||||
// This file is part of ProtonMail Bridge.
|
|
||||||
//
|
|
||||||
// ProtonMail 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.
|
|
||||||
//
|
|
||||||
// ProtonMail 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 ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
package rfc5322
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/mail"
|
|
||||||
|
|
||||||
"github.com/ProtonMail/proton-bridge/pkg/message/rfc5322/parser"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
|
||||||
|
|
||||||
type groupList struct {
|
|
||||||
addresses []*mail.Address
|
|
||||||
}
|
|
||||||
|
|
||||||
func (gl *groupList) withMailboxList(mailboxList *mailboxList) {
|
|
||||||
gl.addresses = append(gl.addresses, mailboxList.addresses...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) EnterGroupList(ctx *parser.GroupListContext) {
|
|
||||||
logrus.WithField("text", ctx.GetText()).Trace("Entering groupList")
|
|
||||||
w.enter(&groupList{})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) ExitGroupList(ctx *parser.GroupListContext) {
|
|
||||||
logrus.WithField("text", ctx.GetText()).Trace("Exiting groupList")
|
|
||||||
|
|
||||||
type withGroupList interface {
|
|
||||||
withGroupList(*groupList)
|
|
||||||
}
|
|
||||||
|
|
||||||
res := w.exit().(*groupList)
|
|
||||||
|
|
||||||
if parent, ok := w.parent().(withGroupList); ok {
|
|
||||||
parent.withGroupList(res)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,62 +0,0 @@
|
|||||||
// Copyright (c) 2020 Proton Technologies AG
|
|
||||||
//
|
|
||||||
// This file is part of ProtonMail Bridge.
|
|
||||||
//
|
|
||||||
// ProtonMail 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.
|
|
||||||
//
|
|
||||||
// ProtonMail 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 ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
package rfc5322
|
|
||||||
|
|
||||||
import (
|
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"github.com/ProtonMail/proton-bridge/pkg/message/rfc5322/parser"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
|
||||||
|
|
||||||
type hour struct {
|
|
||||||
value int
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) EnterHour(ctx *parser.HourContext) {
|
|
||||||
logrus.WithField("text", ctx.GetText()).Trace("Entering hour")
|
|
||||||
|
|
||||||
var text string
|
|
||||||
|
|
||||||
for _, digit := range ctx.AllDigit() {
|
|
||||||
text += digit.GetText()
|
|
||||||
}
|
|
||||||
|
|
||||||
val, err := strconv.Atoi(text)
|
|
||||||
if err != nil {
|
|
||||||
w.err = err
|
|
||||||
}
|
|
||||||
|
|
||||||
w.enter(&hour{
|
|
||||||
value: val,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) ExitHour(ctx *parser.HourContext) {
|
|
||||||
logrus.WithField("text", ctx.GetText()).Trace("Exiting hour")
|
|
||||||
|
|
||||||
type withHour interface {
|
|
||||||
withHour(*hour)
|
|
||||||
}
|
|
||||||
|
|
||||||
res := w.exit().(*hour)
|
|
||||||
|
|
||||||
if parent, ok := w.parent().(withHour); ok {
|
|
||||||
parent.withHour(res)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,60 +0,0 @@
|
|||||||
// Copyright (c) 2020 Proton Technologies AG
|
|
||||||
//
|
|
||||||
// This file is part of ProtonMail Bridge.
|
|
||||||
//
|
|
||||||
// ProtonMail 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.
|
|
||||||
//
|
|
||||||
// ProtonMail 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 ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
package rfc5322
|
|
||||||
|
|
||||||
import (
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/ProtonMail/proton-bridge/pkg/message/rfc5322/parser"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
|
||||||
|
|
||||||
type localPart struct {
|
|
||||||
value string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *localPart) withDotAtom(dotAtom *dotAtom) {
|
|
||||||
p.value = dotAtom.value
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *localPart) withQuotedString(quotedString *quotedString) {
|
|
||||||
p.value = quotedString.value
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *localPart) withObsLocalPart(obsLocalPart *obsLocalPart) {
|
|
||||||
p.value = strings.Join(obsLocalPart.words, ".")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) EnterLocalPart(ctx *parser.LocalPartContext) {
|
|
||||||
logrus.WithField("text", ctx.GetText()).Trace("Entering localPart")
|
|
||||||
w.enter(&localPart{})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) ExitLocalPart(ctx *parser.LocalPartContext) {
|
|
||||||
logrus.WithField("text", ctx.GetText()).Trace("Exiting localPart")
|
|
||||||
|
|
||||||
type withLocalPart interface {
|
|
||||||
withLocalPart(*localPart)
|
|
||||||
}
|
|
||||||
|
|
||||||
res := w.exit().(*localPart)
|
|
||||||
|
|
||||||
if parent, ok := w.parent().(withLocalPart); ok {
|
|
||||||
parent.withLocalPart(res)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,57 +0,0 @@
|
|||||||
// Copyright (c) 2020 Proton Technologies AG
|
|
||||||
//
|
|
||||||
// This file is part of ProtonMail Bridge.
|
|
||||||
//
|
|
||||||
// ProtonMail 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.
|
|
||||||
//
|
|
||||||
// ProtonMail 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 ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
package rfc5322
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/ProtonMail/proton-bridge/pkg/message/rfc5322/parser"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
|
||||||
|
|
||||||
type mailbox struct {
|
|
||||||
name, address string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *mailbox) withNameAddr(nameAddr *nameAddr) {
|
|
||||||
m.name = nameAddr.name
|
|
||||||
m.address = nameAddr.address
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *mailbox) withAddrSpec(addrSpec *addrSpec) {
|
|
||||||
m.address = fmt.Sprintf("%v@%v", addrSpec.localPart, addrSpec.domain)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) EnterMailbox(ctx *parser.MailboxContext) {
|
|
||||||
logrus.WithField("text", ctx.GetText()).Trace("Entering mailbox")
|
|
||||||
w.enter(&mailbox{})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) ExitMailbox(ctx *parser.MailboxContext) {
|
|
||||||
logrus.WithField("text", ctx.GetText()).Trace("Exiting mailbox")
|
|
||||||
|
|
||||||
type withMailbox interface {
|
|
||||||
withMailbox(*mailbox)
|
|
||||||
}
|
|
||||||
|
|
||||||
res := w.exit().(*mailbox)
|
|
||||||
|
|
||||||
if parent, ok := w.parent().(withMailbox); ok {
|
|
||||||
parent.withMailbox(res)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,59 +0,0 @@
|
|||||||
// Copyright (c) 2020 Proton Technologies AG
|
|
||||||
//
|
|
||||||
// This file is part of ProtonMail Bridge.
|
|
||||||
//
|
|
||||||
// ProtonMail 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.
|
|
||||||
//
|
|
||||||
// ProtonMail 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 ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
package rfc5322
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/mail"
|
|
||||||
|
|
||||||
"github.com/ProtonMail/proton-bridge/pkg/message/rfc5322/parser"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
|
||||||
|
|
||||||
type mailboxList struct {
|
|
||||||
addresses []*mail.Address
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ml *mailboxList) withMailbox(mailbox *mailbox) {
|
|
||||||
ml.addresses = append(ml.addresses, &mail.Address{
|
|
||||||
Name: mailbox.name,
|
|
||||||
Address: mailbox.address,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ml *mailboxList) withObsMboxList(obsMboxList *obsMboxList) {
|
|
||||||
ml.addresses = append(ml.addresses, obsMboxList.addresses...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) EnterMailboxList(ctx *parser.MailboxListContext) {
|
|
||||||
logrus.WithField("text", ctx.GetText()).Trace("Entering mailboxList")
|
|
||||||
w.enter(&mailboxList{})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) ExitMailboxList(ctx *parser.MailboxListContext) {
|
|
||||||
logrus.WithField("text", ctx.GetText()).Trace("Exiting mailboxList")
|
|
||||||
|
|
||||||
type withMailboxList interface {
|
|
||||||
withMailboxList(*mailboxList)
|
|
||||||
}
|
|
||||||
|
|
||||||
res := w.exit().(*mailboxList)
|
|
||||||
|
|
||||||
if parent, ok := w.parent().(withMailboxList); ok {
|
|
||||||
parent.withMailboxList(res)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,62 +0,0 @@
|
|||||||
// Copyright (c) 2020 Proton Technologies AG
|
|
||||||
//
|
|
||||||
// This file is part of ProtonMail Bridge.
|
|
||||||
//
|
|
||||||
// ProtonMail 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.
|
|
||||||
//
|
|
||||||
// ProtonMail 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 ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
package rfc5322
|
|
||||||
|
|
||||||
import (
|
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"github.com/ProtonMail/proton-bridge/pkg/message/rfc5322/parser"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
|
||||||
|
|
||||||
type minute struct {
|
|
||||||
value int
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) EnterMinute(ctx *parser.MinuteContext) {
|
|
||||||
logrus.WithField("text", ctx.GetText()).Trace("Entering minute")
|
|
||||||
|
|
||||||
var text string
|
|
||||||
|
|
||||||
for _, digit := range ctx.AllDigit() {
|
|
||||||
text += digit.GetText()
|
|
||||||
}
|
|
||||||
|
|
||||||
val, err := strconv.Atoi(text)
|
|
||||||
if err != nil {
|
|
||||||
w.err = err
|
|
||||||
}
|
|
||||||
|
|
||||||
w.enter(&minute{
|
|
||||||
value: val,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) ExitMinute(ctx *parser.MinuteContext) {
|
|
||||||
logrus.WithField("text", ctx.GetText()).Trace("Exiting minute")
|
|
||||||
|
|
||||||
type withMinute interface {
|
|
||||||
withMinute(*minute)
|
|
||||||
}
|
|
||||||
|
|
||||||
res := w.exit().(*minute)
|
|
||||||
|
|
||||||
if parent, ok := w.parent().(withMinute); ok {
|
|
||||||
parent.withMinute(res)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,84 +0,0 @@
|
|||||||
// Copyright (c) 2020 Proton Technologies AG
|
|
||||||
//
|
|
||||||
// This file is part of ProtonMail Bridge.
|
|
||||||
//
|
|
||||||
// ProtonMail 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.
|
|
||||||
//
|
|
||||||
// ProtonMail 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 ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
package rfc5322
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/ProtonMail/proton-bridge/pkg/message/rfc5322/parser"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
|
||||||
|
|
||||||
type month struct {
|
|
||||||
value time.Month
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) EnterMonth(ctx *parser.MonthContext) {
|
|
||||||
logrus.WithField("text", ctx.GetText()).Trace("Entering month")
|
|
||||||
|
|
||||||
var m time.Month
|
|
||||||
|
|
||||||
switch strings.ToLower(ctx.GetText()) {
|
|
||||||
case "jan":
|
|
||||||
m = time.January
|
|
||||||
case "feb":
|
|
||||||
m = time.February
|
|
||||||
case "mar":
|
|
||||||
m = time.March
|
|
||||||
case "apr":
|
|
||||||
m = time.April
|
|
||||||
case "may":
|
|
||||||
m = time.May
|
|
||||||
case "jun":
|
|
||||||
m = time.June
|
|
||||||
case "jul":
|
|
||||||
m = time.July
|
|
||||||
case "aug":
|
|
||||||
m = time.August
|
|
||||||
case "sep":
|
|
||||||
m = time.September
|
|
||||||
case "oct":
|
|
||||||
m = time.October
|
|
||||||
case "nov":
|
|
||||||
m = time.November
|
|
||||||
case "dec":
|
|
||||||
m = time.December
|
|
||||||
default:
|
|
||||||
w.err = errors.New("no such month")
|
|
||||||
}
|
|
||||||
|
|
||||||
w.enter(&month{
|
|
||||||
value: m,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) ExitMonth(ctx *parser.MonthContext) {
|
|
||||||
logrus.WithField("text", ctx.GetText()).Trace("Exiting month")
|
|
||||||
|
|
||||||
type withMonth interface {
|
|
||||||
withMonth(*month)
|
|
||||||
}
|
|
||||||
|
|
||||||
res := w.exit().(*month)
|
|
||||||
|
|
||||||
if parent, ok := w.parent().(withMonth); ok {
|
|
||||||
parent.withMonth(res)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,56 +0,0 @@
|
|||||||
// Copyright (c) 2020 Proton Technologies AG
|
|
||||||
//
|
|
||||||
// This file is part of ProtonMail Bridge.
|
|
||||||
//
|
|
||||||
// ProtonMail 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.
|
|
||||||
//
|
|
||||||
// ProtonMail 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 ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
package rfc5322
|
|
||||||
|
|
||||||
import (
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/ProtonMail/proton-bridge/pkg/message/rfc5322/parser"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
|
||||||
|
|
||||||
type nameAddr struct {
|
|
||||||
name, address string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *nameAddr) withDisplayName(displayName *displayName) {
|
|
||||||
a.name = strings.Join(displayName.words, " ")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *nameAddr) withAngleAddr(angleAddr *angleAddr) {
|
|
||||||
a.address = angleAddr.address
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) EnterNameAddr(ctx *parser.NameAddrContext) {
|
|
||||||
logrus.WithField("text", ctx.GetText()).Trace("Entering nameAddr")
|
|
||||||
w.enter(&nameAddr{})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) ExitNameAddr(ctx *parser.NameAddrContext) {
|
|
||||||
logrus.WithField("text", ctx.GetText()).Trace("Exiting nameAddr")
|
|
||||||
|
|
||||||
type withNameAddr interface {
|
|
||||||
withNameAddr(*nameAddr)
|
|
||||||
}
|
|
||||||
|
|
||||||
res := w.exit().(*nameAddr)
|
|
||||||
|
|
||||||
if parent, ok := w.parent().(withNameAddr); ok {
|
|
||||||
parent.withNameAddr(res)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,54 +0,0 @@
|
|||||||
// Copyright (c) 2020 Proton Technologies AG
|
|
||||||
//
|
|
||||||
// This file is part of ProtonMail Bridge.
|
|
||||||
//
|
|
||||||
// ProtonMail 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.
|
|
||||||
//
|
|
||||||
// ProtonMail 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 ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
package rfc5322
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/ProtonMail/proton-bridge/pkg/message/rfc5322/parser"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
|
||||||
|
|
||||||
// When interpreting addresses, the route portion SHOULD be ignored.
|
|
||||||
|
|
||||||
type obsAngleAddr struct {
|
|
||||||
address string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *obsAngleAddr) withAddrSpec(addrSpec *addrSpec) {
|
|
||||||
a.address = fmt.Sprintf("%v@%v", addrSpec.localPart, addrSpec.domain)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) EnterObsAngleAddr(ctx *parser.ObsAngleAddrContext) {
|
|
||||||
logrus.WithField("text", ctx.GetText()).Trace("Entering obsAngleAddr")
|
|
||||||
w.enter(&obsAngleAddr{})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) ExitObsAngleAddr(ctx *parser.ObsAngleAddrContext) {
|
|
||||||
logrus.WithField("text", ctx.GetText()).Trace("Exiting obsAngleAddr")
|
|
||||||
|
|
||||||
type withObsAngleAddr interface {
|
|
||||||
withObsAngleAddr(*obsAngleAddr)
|
|
||||||
}
|
|
||||||
|
|
||||||
res := w.exit().(*obsAngleAddr)
|
|
||||||
|
|
||||||
if parent, ok := w.parent().(withObsAngleAddr); ok {
|
|
||||||
parent.withObsAngleAddr(res)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,50 +0,0 @@
|
|||||||
// Copyright (c) 2020 Proton Technologies AG
|
|
||||||
//
|
|
||||||
// This file is part of ProtonMail Bridge.
|
|
||||||
//
|
|
||||||
// ProtonMail 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.
|
|
||||||
//
|
|
||||||
// ProtonMail 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 ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
package rfc5322
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/ProtonMail/proton-bridge/pkg/message/rfc5322/parser"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
|
||||||
|
|
||||||
type obsDomain struct {
|
|
||||||
atoms []string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *obsDomain) withAtom(atom *atom) {
|
|
||||||
p.atoms = append(p.atoms, atom.value)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) EnterObsDomain(ctx *parser.ObsDomainContext) {
|
|
||||||
logrus.WithField("text", ctx.GetText()).Trace("Entering obsDomain")
|
|
||||||
w.enter(&obsDomain{})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) ExitObsDomain(ctx *parser.ObsDomainContext) {
|
|
||||||
logrus.WithField("text", ctx.GetText()).Trace("Exiting obsDomain")
|
|
||||||
|
|
||||||
type withObsDomain interface {
|
|
||||||
withObsDomain(*obsDomain)
|
|
||||||
}
|
|
||||||
|
|
||||||
res := w.exit().(*obsDomain)
|
|
||||||
|
|
||||||
if parent, ok := w.parent().(withObsDomain); ok {
|
|
||||||
parent.withObsDomain(res)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,50 +0,0 @@
|
|||||||
// Copyright (c) 2020 Proton Technologies AG
|
|
||||||
//
|
|
||||||
// This file is part of ProtonMail Bridge.
|
|
||||||
//
|
|
||||||
// ProtonMail 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.
|
|
||||||
//
|
|
||||||
// ProtonMail 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 ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
package rfc5322
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/ProtonMail/proton-bridge/pkg/message/rfc5322/parser"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
|
||||||
|
|
||||||
type obsLocalPart struct {
|
|
||||||
words []string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *obsLocalPart) withWord(word *word) {
|
|
||||||
p.words = append(p.words, word.value)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) EnterObsLocalPart(ctx *parser.ObsLocalPartContext) {
|
|
||||||
logrus.WithField("text", ctx.GetText()).Trace("Entering obsLocalPart")
|
|
||||||
w.enter(&obsLocalPart{})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) ExitObsLocalPart(ctx *parser.ObsLocalPartContext) {
|
|
||||||
logrus.WithField("text", ctx.GetText()).Trace("Exiting obsLocalPart")
|
|
||||||
|
|
||||||
type withObsLocalPart interface {
|
|
||||||
withObsLocalPart(*obsLocalPart)
|
|
||||||
}
|
|
||||||
|
|
||||||
res := w.exit().(*obsLocalPart)
|
|
||||||
|
|
||||||
if parent, ok := w.parent().(withObsLocalPart); ok {
|
|
||||||
parent.withObsLocalPart(res)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,55 +0,0 @@
|
|||||||
// Copyright (c) 2020 Proton Technologies AG
|
|
||||||
//
|
|
||||||
// This file is part of ProtonMail Bridge.
|
|
||||||
//
|
|
||||||
// ProtonMail 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.
|
|
||||||
//
|
|
||||||
// ProtonMail 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 ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
package rfc5322
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/mail"
|
|
||||||
|
|
||||||
"github.com/ProtonMail/proton-bridge/pkg/message/rfc5322/parser"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
|
||||||
|
|
||||||
type obsMboxList struct {
|
|
||||||
addresses []*mail.Address
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ml *obsMboxList) withMailbox(mailbox *mailbox) {
|
|
||||||
ml.addresses = append(ml.addresses, &mail.Address{
|
|
||||||
Name: mailbox.name,
|
|
||||||
Address: mailbox.address,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) EnterObsMboxList(ctx *parser.ObsMboxListContext) {
|
|
||||||
logrus.WithField("text", ctx.GetText()).Trace("Entering obsMboxList")
|
|
||||||
w.enter(&obsMboxList{})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) ExitObsMboxList(ctx *parser.ObsMboxListContext) {
|
|
||||||
logrus.WithField("text", ctx.GetText()).Trace("Exiting obsMboxList")
|
|
||||||
|
|
||||||
type withObsMboxList interface {
|
|
||||||
withObsMboxList(*obsMboxList)
|
|
||||||
}
|
|
||||||
|
|
||||||
res := w.exit().(*obsMboxList)
|
|
||||||
|
|
||||||
if parent, ok := w.parent().(withObsMboxList); ok {
|
|
||||||
parent.withObsMboxList(res)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,82 +0,0 @@
|
|||||||
// Copyright (c) 2020 Proton Technologies AG
|
|
||||||
//
|
|
||||||
// This file is part of ProtonMail Bridge.
|
|
||||||
//
|
|
||||||
// ProtonMail 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.
|
|
||||||
//
|
|
||||||
// ProtonMail 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 ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
package rfc5322
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/ProtonMail/proton-bridge/pkg/message/rfc5322/parser"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
|
||||||
|
|
||||||
type obsZone struct {
|
|
||||||
location *time.Location
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) EnterObsZone(ctx *parser.ObsZoneContext) {
|
|
||||||
logrus.WithField("text", ctx.GetText()).Trace("Entering obsZone")
|
|
||||||
|
|
||||||
loc := time.UTC
|
|
||||||
|
|
||||||
switch strings.ToLower(ctx.GetText()) {
|
|
||||||
case "ut":
|
|
||||||
loc = time.FixedZone(ctx.GetText(), 0)
|
|
||||||
case "utc":
|
|
||||||
loc = time.FixedZone(ctx.GetText(), 0)
|
|
||||||
case "gmt":
|
|
||||||
loc = time.FixedZone(ctx.GetText(), 0)
|
|
||||||
case "est":
|
|
||||||
loc = time.FixedZone(ctx.GetText(), -5*60*60)
|
|
||||||
case "edt":
|
|
||||||
loc = time.FixedZone(ctx.GetText(), -4*60*60)
|
|
||||||
case "cst":
|
|
||||||
loc = time.FixedZone(ctx.GetText(), -6*60*60)
|
|
||||||
case "cdt":
|
|
||||||
loc = time.FixedZone(ctx.GetText(), -5*60*60)
|
|
||||||
case "mst":
|
|
||||||
loc = time.FixedZone(ctx.GetText(), -7*60*60)
|
|
||||||
case "mdt":
|
|
||||||
loc = time.FixedZone(ctx.GetText(), -6*60*60)
|
|
||||||
case "pst":
|
|
||||||
loc = time.FixedZone(ctx.GetText(), -8*60*60)
|
|
||||||
case "pdt":
|
|
||||||
loc = time.FixedZone(ctx.GetText(), -7*60*60)
|
|
||||||
default:
|
|
||||||
w.err = errors.New("bad timezone")
|
|
||||||
}
|
|
||||||
|
|
||||||
w.enter(&obsZone{
|
|
||||||
location: loc,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) ExitObsZone(ctx *parser.ObsZoneContext) {
|
|
||||||
logrus.WithField("text", ctx.GetText()).Trace("Exiting obsZone")
|
|
||||||
|
|
||||||
type withObsZone interface {
|
|
||||||
withObsZone(*obsZone)
|
|
||||||
}
|
|
||||||
|
|
||||||
res := w.exit().(*obsZone)
|
|
||||||
|
|
||||||
if parent, ok := w.parent().(withObsZone); ok {
|
|
||||||
parent.withObsZone(res)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,73 +0,0 @@
|
|||||||
// Copyright (c) 2020 Proton Technologies AG
|
|
||||||
//
|
|
||||||
// This file is part of ProtonMail Bridge.
|
|
||||||
//
|
|
||||||
// ProtonMail 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.
|
|
||||||
//
|
|
||||||
// ProtonMail 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 ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
package rfc5322
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/ProtonMail/proton-bridge/pkg/message/rfc5322/parser"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
|
||||||
|
|
||||||
type offset struct {
|
|
||||||
rep string
|
|
||||||
value int
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) EnterOffset(ctx *parser.OffsetContext) {
|
|
||||||
logrus.WithField("text", ctx.GetText()).Trace("Entering offset")
|
|
||||||
|
|
||||||
text := ctx.GetText()
|
|
||||||
|
|
||||||
// NOTE: RFC5322 date-time should always begin with + or -
|
|
||||||
// but we relax that requirement a bit due to many messages
|
|
||||||
// in the wild that skip the +; we add the "+" if missing.
|
|
||||||
if !strings.HasPrefix(text, "+") && !strings.HasPrefix(text, "-") {
|
|
||||||
text = "+" + text
|
|
||||||
}
|
|
||||||
|
|
||||||
sgn := text[0:1]
|
|
||||||
hrs := text[1:3]
|
|
||||||
min := text[3:5]
|
|
||||||
|
|
||||||
dur, err := time.ParseDuration(fmt.Sprintf("%v%vh%vm", sgn, hrs, min))
|
|
||||||
if err != nil {
|
|
||||||
w.err = err
|
|
||||||
}
|
|
||||||
|
|
||||||
w.enter(&offset{
|
|
||||||
rep: text,
|
|
||||||
value: int(dur.Seconds()),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) ExitOffset(ctx *parser.OffsetContext) {
|
|
||||||
logrus.WithField("text", ctx.GetText()).Trace("Exiting offset")
|
|
||||||
|
|
||||||
type withOffset interface {
|
|
||||||
withOffset(*offset)
|
|
||||||
}
|
|
||||||
|
|
||||||
res := w.exit().(*offset)
|
|
||||||
|
|
||||||
if parent, ok := w.parent().(withOffset); ok {
|
|
||||||
parent.withOffset(res)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,701 +0,0 @@
|
|||||||
// Copyright (c) 2020 Proton Technologies AG
|
|
||||||
//
|
|
||||||
// This file is part of ProtonMail Bridge.
|
|
||||||
//
|
|
||||||
// ProtonMail 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.
|
|
||||||
//
|
|
||||||
// ProtonMail 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 ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
package rfc5322
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/xml"
|
|
||||||
"io"
|
|
||||||
"net/mail"
|
|
||||||
"os"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestParseSingleAddress(t *testing.T) {
|
|
||||||
tests := []struct {
|
|
||||||
input string
|
|
||||||
addrs []*mail.Address
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
input: `user@example.com`,
|
|
||||||
addrs: []*mail.Address{{
|
|
||||||
Address: `user@example.com`,
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `John Doe <jdoe@machine.example>`,
|
|
||||||
addrs: []*mail.Address{{
|
|
||||||
Name: `John Doe`,
|
|
||||||
Address: `jdoe@machine.example`,
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `Mary Smith <mary@example.net>`,
|
|
||||||
addrs: []*mail.Address{{
|
|
||||||
Name: `Mary Smith`,
|
|
||||||
Address: `mary@example.net`,
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `"Joe Q. Public" <john.q.public@example.com>`,
|
|
||||||
addrs: []*mail.Address{{
|
|
||||||
Name: `Joe Q. Public`,
|
|
||||||
Address: `john.q.public@example.com`,
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `Mary Smith <mary@x.test>`,
|
|
||||||
addrs: []*mail.Address{{
|
|
||||||
Name: `Mary Smith`,
|
|
||||||
Address: `mary@x.test`,
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `jdoe@example.org`,
|
|
||||||
addrs: []*mail.Address{{
|
|
||||||
Address: `jdoe@example.org`,
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `Who? <one@y.test>`,
|
|
||||||
addrs: []*mail.Address{{
|
|
||||||
Name: `Who?`,
|
|
||||||
Address: `one@y.test`,
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `<boss@nil.test>`,
|
|
||||||
addrs: []*mail.Address{{
|
|
||||||
Address: `boss@nil.test`,
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `"Giant; \"Big\" Box" <sysservices@example.net>`,
|
|
||||||
addrs: []*mail.Address{{
|
|
||||||
Name: `Giant; "Big" Box`,
|
|
||||||
Address: `sysservices@example.net`,
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `Pete <pete@silly.example>`,
|
|
||||||
addrs: []*mail.Address{{
|
|
||||||
Name: `Pete`,
|
|
||||||
Address: `pete@silly.example`,
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `"Mary Smith: Personal Account" <smith@home.example>`,
|
|
||||||
addrs: []*mail.Address{{
|
|
||||||
Name: `Mary Smith: Personal Account`,
|
|
||||||
Address: `smith@home.example`,
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `Pete(A nice \) chap) <pete(his account)@silly.test(his host)>`,
|
|
||||||
addrs: []*mail.Address{{
|
|
||||||
Name: `Pete`,
|
|
||||||
Address: `pete@silly.test`,
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `Gogh Fir <gf@example.com>`,
|
|
||||||
addrs: []*mail.Address{{
|
|
||||||
Name: `Gogh Fir`,
|
|
||||||
Address: `gf@example.com`,
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `normal name <username@server.com>`,
|
|
||||||
addrs: []*mail.Address{{
|
|
||||||
Name: `normal name`,
|
|
||||||
Address: `username@server.com`,
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `"comma, name" <username@server.com>`,
|
|
||||||
addrs: []*mail.Address{{
|
|
||||||
Name: `comma, name`,
|
|
||||||
Address: `username@server.com`,
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `name <username@server.com> (ignore comment)`,
|
|
||||||
addrs: []*mail.Address{{
|
|
||||||
Name: `name`,
|
|
||||||
Address: `username@server.com`,
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `"Mail Robot" <>`,
|
|
||||||
addrs: []*mail.Address{{
|
|
||||||
Name: `Mail Robot`,
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `Michal Hořejšek <hořejšek@mail.com>`,
|
|
||||||
addrs: []*mail.Address{{
|
|
||||||
Name: `Michal Hořejšek`,
|
|
||||||
Address: `hořejšek@mail.com`, // Not his real address.
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `First Last <user@domain.com >`,
|
|
||||||
addrs: []*mail.Address{{
|
|
||||||
Name: `First Last`,
|
|
||||||
Address: `user@domain.com`,
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `First Last <user@domain.com. >`,
|
|
||||||
addrs: []*mail.Address{{
|
|
||||||
Name: `First Last`,
|
|
||||||
Address: `user@domain.com.`,
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `First Last <user@domain.com.>`,
|
|
||||||
addrs: []*mail.Address{{
|
|
||||||
Name: `First Last`,
|
|
||||||
Address: `user@domain.com.`,
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `First Last <user@domain.com:25>`,
|
|
||||||
addrs: []*mail.Address{{
|
|
||||||
Name: `First Last`,
|
|
||||||
Address: `user@domain.com:25`,
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `First Last <user@[10.0.0.1]>`,
|
|
||||||
addrs: []*mail.Address{{
|
|
||||||
Name: `First Last`,
|
|
||||||
Address: `user@[10.0.0.1]`,
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `<postmaster@[10.10.10.10]>`,
|
|
||||||
addrs: []*mail.Address{
|
|
||||||
{
|
|
||||||
Address: `postmaster@[10.10.10.10]`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `user@domain <user@domain.com>`,
|
|
||||||
addrs: []*mail.Address{{
|
|
||||||
// Name: `user@domain`,
|
|
||||||
Name: `user @ domain`,
|
|
||||||
Address: `user@domain.com`,
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `First Last < user@domain.com>`,
|
|
||||||
addrs: []*mail.Address{{
|
|
||||||
Name: `First Last`,
|
|
||||||
Address: `user@domain.com`,
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `First Middle @ Last <user@domain.com>`,
|
|
||||||
addrs: []*mail.Address{{
|
|
||||||
Name: `First Middle @ Last`,
|
|
||||||
Address: `user@domain.com`,
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `user@domain.com,`,
|
|
||||||
addrs: []*mail.Address{
|
|
||||||
{
|
|
||||||
Address: `user@domain.com`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `First Middle "Last" <user@domain.com>`,
|
|
||||||
addrs: []*mail.Address{
|
|
||||||
{
|
|
||||||
Name: `First Middle Last`,
|
|
||||||
Address: `user@domain.com`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `First Middle Last <user@domain.com>`,
|
|
||||||
addrs: []*mail.Address{
|
|
||||||
{
|
|
||||||
Name: `First Middle Last`,
|
|
||||||
Address: `user@domain.com`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `First Middle"Last" <user@domain.com>`,
|
|
||||||
addrs: []*mail.Address{
|
|
||||||
{
|
|
||||||
Name: `First Middle Last`,
|
|
||||||
Address: `user@domain.com`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `First Middle "Last"<user@domain.com>`,
|
|
||||||
addrs: []*mail.Address{
|
|
||||||
{
|
|
||||||
Name: `First Middle Last`,
|
|
||||||
Address: `user@domain.com`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `First "Middle" "Last" <user@domain.com>`,
|
|
||||||
addrs: []*mail.Address{
|
|
||||||
{
|
|
||||||
Name: `First Middle Last`,
|
|
||||||
Address: `user@domain.com`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `First "Middle""Last" <user@domain.com>`,
|
|
||||||
addrs: []*mail.Address{
|
|
||||||
{
|
|
||||||
Name: `First Middle Last`,
|
|
||||||
Address: `user@domain.com`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, test := range tests {
|
|
||||||
test := test
|
|
||||||
|
|
||||||
t.Run(test.input, func(t *testing.T) {
|
|
||||||
addrs, err := ParseAddressList(test.input)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.ElementsMatch(t, test.addrs, addrs)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestParseSingleAddressEncodedWord(t *testing.T) {
|
|
||||||
tests := []struct {
|
|
||||||
input string
|
|
||||||
addrs []*mail.Address
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
input: `=?US-ASCII?Q?Keith_Moore?= <moore@cs.utk.edu>`,
|
|
||||||
addrs: []*mail.Address{{
|
|
||||||
Name: `Keith Moore`,
|
|
||||||
Address: `moore@cs.utk.edu`,
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `=?ISO-8859-1?Q?Keld_J=F8rn_Simonsen?= <keld@dkuug.dk>`,
|
|
||||||
addrs: []*mail.Address{{
|
|
||||||
Name: `Keld Jørn Simonsen`,
|
|
||||||
Address: `keld@dkuug.dk`,
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `=?ISO-8859-1?Q?Andr=E9?= Pirard <PIRARD@vm1.ulg.ac.be>`,
|
|
||||||
addrs: []*mail.Address{{
|
|
||||||
Name: `André Pirard`,
|
|
||||||
Address: `PIRARD@vm1.ulg.ac.be`,
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `=?ISO-8859-1?Q?Olle_J=E4rnefors?= <ojarnef@admin.kth.se>`,
|
|
||||||
addrs: []*mail.Address{{
|
|
||||||
Name: `Olle Järnefors`,
|
|
||||||
Address: `ojarnef@admin.kth.se`,
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `=?ISO-8859-1?Q?Patrik_F=E4ltstr=F6m?= <paf@nada.kth.se>`,
|
|
||||||
addrs: []*mail.Address{{
|
|
||||||
Name: `Patrik Fältström`,
|
|
||||||
Address: `paf@nada.kth.se`,
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `Nathaniel Borenstein <nsb@thumper.bellcore.com> (=?iso-8859-8?b?7eXs+SDv4SDp7Oj08A==?=)`,
|
|
||||||
addrs: []*mail.Address{{
|
|
||||||
Name: `Nathaniel Borenstein`,
|
|
||||||
Address: `nsb@thumper.bellcore.com`,
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `=?UTF-8?B?PEJlemUgam3DqW5hPg==?= <user@domain.com>`,
|
|
||||||
addrs: []*mail.Address{
|
|
||||||
{
|
|
||||||
Name: `<Beze jména>`,
|
|
||||||
Address: `user@domain.com`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `First Middle =?utf-8?Q?Last?= <user@domain.com>`,
|
|
||||||
addrs: []*mail.Address{
|
|
||||||
{
|
|
||||||
Name: `First Middle Last`,
|
|
||||||
Address: `user@domain.com`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
/*
|
|
||||||
{
|
|
||||||
input: `First Middle=?utf-8?Q?Last?= <user@domain.com>`,
|
|
||||||
addrs: []*mail.Address{
|
|
||||||
{
|
|
||||||
Name: `First Middle Last`,
|
|
||||||
Address: `user@domain.com`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
*/
|
|
||||||
{
|
|
||||||
input: `First Middle =?utf-8?Q?Last?=<user@domain.com>`,
|
|
||||||
addrs: []*mail.Address{
|
|
||||||
{
|
|
||||||
Name: `First Middle Last`,
|
|
||||||
Address: `user@domain.com`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `First =?utf-8?Q?Middle?= =?utf-8?Q?Last?= <user@domain.com>`,
|
|
||||||
addrs: []*mail.Address{
|
|
||||||
{
|
|
||||||
Name: `First Middle Last`,
|
|
||||||
Address: `user@domain.com`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `First =?utf-8?Q?Middle?==?utf-8?Q?Last?= <user@domain.com>`,
|
|
||||||
addrs: []*mail.Address{
|
|
||||||
{
|
|
||||||
Name: `First Middle Last`,
|
|
||||||
Address: `user@domain.com`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `First "Middle"=?utf-8?Q?Last?= <user@domain.com>`,
|
|
||||||
addrs: []*mail.Address{
|
|
||||||
{
|
|
||||||
Name: `First Middle Last`,
|
|
||||||
Address: `user@domain.com`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `First "Middle" =?utf-8?Q?Last?= <user@domain.com>`,
|
|
||||||
addrs: []*mail.Address{
|
|
||||||
{
|
|
||||||
Name: `First Middle Last`,
|
|
||||||
Address: `user@domain.com`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `First "Middle" =?utf-8?Q?Last?=<user@domain.com>`,
|
|
||||||
addrs: []*mail.Address{
|
|
||||||
{
|
|
||||||
Name: `First Middle Last`,
|
|
||||||
Address: `user@domain.com`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `=?UTF-8?B?PEJlemUgam3DqW5hPg==?= <user@domain.com>`,
|
|
||||||
addrs: []*mail.Address{
|
|
||||||
{
|
|
||||||
Name: `<Beze jména>`,
|
|
||||||
Address: `user@domain.com`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, test := range tests {
|
|
||||||
test := test
|
|
||||||
|
|
||||||
t.Run(test.input, func(t *testing.T) {
|
|
||||||
addrs, err := ParseAddressList(test.input)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.ElementsMatch(t, test.addrs, addrs)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestParseAddressList(t *testing.T) {
|
|
||||||
tests := []struct {
|
|
||||||
input string
|
|
||||||
addrs []*mail.Address
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
input: `Alice <alice@example.com>, Bob <bob@example.com>, Eve <eve@example.com>`,
|
|
||||||
addrs: []*mail.Address{
|
|
||||||
{
|
|
||||||
Name: `Alice`,
|
|
||||||
Address: `alice@example.com`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: `Bob`,
|
|
||||||
Address: `bob@example.com`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: `Eve`,
|
|
||||||
Address: `eve@example.com`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `Ed Jones <c@a.test>,joe@where.test,John <jdoe@one.test>`,
|
|
||||||
addrs: []*mail.Address{
|
|
||||||
{
|
|
||||||
Name: `Ed Jones`,
|
|
||||||
Address: `c@a.test`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Address: `joe@where.test`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: `John`,
|
|
||||||
Address: `jdoe@one.test`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `name (ignore comment) <username@server.com>, (Comment as name) username2@server.com`,
|
|
||||||
addrs: []*mail.Address{
|
|
||||||
{
|
|
||||||
Name: `name`,
|
|
||||||
Address: `username@server.com`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Address: `username2@server.com`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `"normal name" <username@server.com>, "comma, name" <address@server.com>`,
|
|
||||||
addrs: []*mail.Address{
|
|
||||||
{
|
|
||||||
Name: `normal name`,
|
|
||||||
Address: `username@server.com`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: `comma, name`,
|
|
||||||
Address: `address@server.com`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `"comma, one" <username@server.com>, "comma, two" <address@server.com>`,
|
|
||||||
addrs: []*mail.Address{
|
|
||||||
{
|
|
||||||
Name: `comma, one`,
|
|
||||||
Address: `username@server.com`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: `comma, two`,
|
|
||||||
Address: `address@server.com`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `normal name <username@server.com>, (comment)All.(around)address@(the)server.com`,
|
|
||||||
addrs: []*mail.Address{
|
|
||||||
{
|
|
||||||
Name: `normal name`,
|
|
||||||
Address: `username@server.com`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Address: `All.address@server.com`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `normal name <username@server.com>, All.("comma, in comment")address@(the)server.com`,
|
|
||||||
addrs: []*mail.Address{
|
|
||||||
{
|
|
||||||
Name: `normal name`,
|
|
||||||
Address: `username@server.com`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Address: `All.address@server.com`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, test := range tests {
|
|
||||||
test := test
|
|
||||||
|
|
||||||
t.Run(test.input, func(t *testing.T) {
|
|
||||||
addrs, err := ParseAddressList(test.input)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.ElementsMatch(t, test.addrs, addrs)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestParseGroup(t *testing.T) {
|
|
||||||
tests := []struct {
|
|
||||||
input string
|
|
||||||
addrs []*mail.Address
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
input: `A Group:Ed Jones <c@a.test>,joe@where.test,John <jdoe@one.test>;`,
|
|
||||||
addrs: []*mail.Address{
|
|
||||||
{
|
|
||||||
Name: `Ed Jones`,
|
|
||||||
Address: `c@a.test`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Address: `joe@where.test`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: `John`,
|
|
||||||
Address: `jdoe@one.test`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `Undisclosed recipients:;`,
|
|
||||||
addrs: []*mail.Address{},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `(Empty list)(start)Hidden recipients :(nobody(that I know)) ;`,
|
|
||||||
addrs: []*mail.Address{},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, test := range tests {
|
|
||||||
test := test
|
|
||||||
|
|
||||||
t.Run(test.input, func(t *testing.T) {
|
|
||||||
addrs, err := ParseAddressList(test.input)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.ElementsMatch(t, test.addrs, addrs)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TestParseRejectedAddresses tests that weird addresses that are rejected by
|
|
||||||
// serverside are also rejected by us. If for some reason we end up being able
|
|
||||||
// to parse these malformed addresses, great! For now let's collect them here.
|
|
||||||
func TestParseRejectedAddresses(t *testing.T) {
|
|
||||||
tests := []struct {
|
|
||||||
input string
|
|
||||||
addrs []*mail.Address
|
|
||||||
}{
|
|
||||||
{input: `"comma, name" <username@server.com>, another, name <address@server.com>`},
|
|
||||||
{input: `username`},
|
|
||||||
{input: `undisclosed-recipients:`},
|
|
||||||
{input: `=?ISO-8859-2?Q?First_Last?= <user@domain.com>, <user@domain.com,First/AAA/BBB/CCC,>`},
|
|
||||||
{input: `user@domain...com`},
|
|
||||||
{input: `=?windows-1250?Q?Spr=E1vce_syst=E9mu?=`},
|
|
||||||
{input: `"'user@domain.com.'"`},
|
|
||||||
{input: `<this is not an email address>`},
|
|
||||||
}
|
|
||||||
for _, test := range tests {
|
|
||||||
test := test
|
|
||||||
|
|
||||||
t.Run(test.input, func(t *testing.T) {
|
|
||||||
_, err := ParseAddressList(test.input)
|
|
||||||
assert.Error(t, err)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TestIsEmailValidCategory runs over the "IsEmail" standard tests,
|
|
||||||
// ensuring it can at least recognize all emails in the "valid" category.
|
|
||||||
// In future, we should expand these tests to run over more categories.
|
|
||||||
func TestIsEmailValidCategory(t *testing.T) {
|
|
||||||
f, err := os.Open("tests.xml")
|
|
||||||
require.NoError(t, err)
|
|
||||||
defer func() { require.NoError(t, err) }()
|
|
||||||
|
|
||||||
for test := range readTestCases(f) {
|
|
||||||
test := test
|
|
||||||
|
|
||||||
if test.category != "ISEMAIL_VALID_CATEGORY" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
t.Run(test.id, func(t *testing.T) {
|
|
||||||
_, err := ParseAddressList(test.address)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type testCase struct {
|
|
||||||
id string
|
|
||||||
address string
|
|
||||||
category string
|
|
||||||
diagnosis string
|
|
||||||
}
|
|
||||||
|
|
||||||
func readTestCases(r io.Reader) chan testCase {
|
|
||||||
ch := make(chan testCase)
|
|
||||||
|
|
||||||
var (
|
|
||||||
test testCase
|
|
||||||
data string
|
|
||||||
)
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
decoder := xml.NewDecoder(r)
|
|
||||||
|
|
||||||
for token, err := decoder.Token(); err == nil; token, err = decoder.Token() {
|
|
||||||
switch t := token.(type) {
|
|
||||||
case xml.StartElement:
|
|
||||||
if t.Name.Local == "test" {
|
|
||||||
test = testCase{
|
|
||||||
id: t.Attr[0].Value,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
case xml.EndElement:
|
|
||||||
switch t.Name.Local {
|
|
||||||
case "test":
|
|
||||||
ch <- test
|
|
||||||
|
|
||||||
case "address":
|
|
||||||
test.address = data
|
|
||||||
|
|
||||||
case "category":
|
|
||||||
test.category = data
|
|
||||||
|
|
||||||
case "diagnosis":
|
|
||||||
test.diagnosis = data
|
|
||||||
}
|
|
||||||
|
|
||||||
case xml.CharData:
|
|
||||||
data = string(t)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
close(ch)
|
|
||||||
}()
|
|
||||||
|
|
||||||
return ch
|
|
||||||
}
|
|
||||||
@ -1,248 +0,0 @@
|
|||||||
// Copyright (c) 2020 Proton Technologies AG
|
|
||||||
//
|
|
||||||
// This file is part of ProtonMail Bridge.
|
|
||||||
//
|
|
||||||
// ProtonMail 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.
|
|
||||||
//
|
|
||||||
// ProtonMail 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 ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
package rfc5322
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestParseDateTime(t *testing.T) {
|
|
||||||
tests := []struct {
|
|
||||||
input string
|
|
||||||
want string
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
input: `Fri, 21 Nov 1997 09:55:06`,
|
|
||||||
want: `1997-11-21T09:55:06Z`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `Fri, 21 Nov 1997 09:55:06 -0600`,
|
|
||||||
want: `1997-11-21T09:55:06-06:00`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `Tue, 1 Jul 2003 10:52:37 +0200`,
|
|
||||||
want: `2003-07-01T10:52:37+02:00`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `Thu, 13 Feb 1969 23:32:54 -0330`,
|
|
||||||
want: `1969-02-13T23:32:54-03:30`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: "Thu, 13 Feb 1969 23:32 -0330 (Newfoundland Time)",
|
|
||||||
want: `1969-02-13T23:32:00-03:30`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `2 Jan 2006 15:04:05 -0700`,
|
|
||||||
want: `2006-01-02T15:04:05-07:00`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `2 Jan 2006 15:04:05 MST`,
|
|
||||||
want: `2006-01-02T15:04:05-07:00`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `2 Jan 2006 15:04 -0700`,
|
|
||||||
want: `2006-01-02T15:04:00-07:00`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `2 Jan 2006 15:04 MST`,
|
|
||||||
want: `2006-01-02T15:04:00-07:00`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `2 Jan 06 15:04:05 -0700`,
|
|
||||||
want: `2006-01-02T15:04:05-07:00`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `2 Jan 06 15:04:05 MST`,
|
|
||||||
want: `2006-01-02T15:04:05-07:00`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `2 Jan 06 15:04 -0700`,
|
|
||||||
want: `2006-01-02T15:04:00-07:00`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `2 Jan 06 15:04 MST`,
|
|
||||||
want: `2006-01-02T15:04:00-07:00`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `02 Jan 2006 15:04:05 -0700`,
|
|
||||||
want: `2006-01-02T15:04:05-07:00`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `02 Jan 2006 15:04:05 MST`,
|
|
||||||
want: `2006-01-02T15:04:05-07:00`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `02 Jan 2006 15:04 -0700`,
|
|
||||||
want: `2006-01-02T15:04:00-07:00`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `02 Jan 2006 15:04 MST`,
|
|
||||||
want: `2006-01-02T15:04:00-07:00`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `02 Jan 06 15:04:05 -0700`,
|
|
||||||
want: `2006-01-02T15:04:05-07:00`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `02 Jan 06 15:04:05 MST`,
|
|
||||||
want: `2006-01-02T15:04:05-07:00`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `02 Jan 06 15:04 -0700`,
|
|
||||||
want: `2006-01-02T15:04:00-07:00`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `02 Jan 06 15:04 MST`,
|
|
||||||
want: `2006-01-02T15:04:00-07:00`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `Mon, 2 Jan 2006 15:04:05 -0700`,
|
|
||||||
want: `2006-01-02T15:04:05-07:00`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `Mon, 2 Jan 2006 15:04:05 MST`,
|
|
||||||
want: `2006-01-02T15:04:05-07:00`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `Mon, 2 Jan 2006 15:04 -0700`,
|
|
||||||
want: `2006-01-02T15:04:00-07:00`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `Mon, 2 Jan 2006 15:04 MST`,
|
|
||||||
want: `2006-01-02T15:04:00-07:00`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `Mon, 2 Jan 06 15:04:05 -0700`,
|
|
||||||
want: `2006-01-02T15:04:05-07:00`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `Mon, 2 Jan 06 15:04:05 MST`,
|
|
||||||
want: `2006-01-02T15:04:05-07:00`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `Mon, 2 Jan 06 15:04 -0700`,
|
|
||||||
want: `2006-01-02T15:04:00-07:00`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `Mon, 2 Jan 06 15:04 MST`,
|
|
||||||
want: `2006-01-02T15:04:00-07:00`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `Mon, 02 Jan 2006 15:04:05 -0700`,
|
|
||||||
want: `2006-01-02T15:04:05-07:00`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `Mon, 02 Jan 2006 15:04:05 MST`,
|
|
||||||
want: `2006-01-02T15:04:05-07:00`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `Mon, 02 Jan 2006 15:04 -0700`,
|
|
||||||
want: `2006-01-02T15:04:00-07:00`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `Mon, 02 Jan 2006 15:04 MST`,
|
|
||||||
want: `2006-01-02T15:04:00-07:00`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `Mon, 02 Jan 06 15:04:05 -0700`,
|
|
||||||
want: `2006-01-02T15:04:05-07:00`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `Mon, 02 Jan 06 15:04:05 MST`,
|
|
||||||
want: `2006-01-02T15:04:05-07:00`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `Mon, 02 Jan 06 15:04 -0700`,
|
|
||||||
want: `2006-01-02T15:04:00-07:00`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `Mon, 02 Jan 06 15:04 MST`,
|
|
||||||
want: `2006-01-02T15:04:00-07:00`,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, test := range tests {
|
|
||||||
test := test
|
|
||||||
|
|
||||||
t.Run(test.input, func(t *testing.T) {
|
|
||||||
got, err := ParseDateTime(test.input)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.Equal(t, test.want, got.Format(time.RFC3339))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestParseDateTimeObsolete(t *testing.T) {
|
|
||||||
tests := []struct {
|
|
||||||
input string
|
|
||||||
want string
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
input: `21 Nov 97 09:55:06 GMT`,
|
|
||||||
want: `1997-11-21T09:55:06Z`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `Wed, 01 Jan 2020 12:00:00 UTC`,
|
|
||||||
want: `2020-01-01T12:00:00Z`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `Wed, 01 Jan 2020 13:00:00 UTC`,
|
|
||||||
want: `2020-01-01T13:00:00Z`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `Wed, 01 Jan 2020 12:30:00 UTC`,
|
|
||||||
want: `2020-01-01T12:30:00Z`,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, test := range tests {
|
|
||||||
test := test
|
|
||||||
|
|
||||||
t.Run(test.input, func(t *testing.T) {
|
|
||||||
got, err := ParseDateTime(test.input)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.Equal(t, test.want, got.Format(time.RFC3339))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestParseDateTimeRelaxed(t *testing.T) {
|
|
||||||
tests := []struct {
|
|
||||||
input string
|
|
||||||
want string
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
input: `Mon, 28 Jan 2019 20:59:01 0000`,
|
|
||||||
want: `2019-01-28T20:59:01Z`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: `Mon, 25 Sep 2017 5:25:40 +0200`,
|
|
||||||
want: `2017-09-25T05:25:40+02:00`,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, test := range tests {
|
|
||||||
test := test
|
|
||||||
|
|
||||||
t.Run(test.input, func(t *testing.T) {
|
|
||||||
got, err := ParseDateTime(test.input)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.Equal(t, test.want, got.Format(time.RFC3339))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,83 +0,0 @@
|
|||||||
// Copyright (c) 2020 Proton Technologies AG
|
|
||||||
//
|
|
||||||
// This file is part of ProtonMail Bridge.
|
|
||||||
//
|
|
||||||
// ProtonMail 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.
|
|
||||||
//
|
|
||||||
// ProtonMail 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 ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
package rfc5322
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/mail"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/ProtonMail/proton-bridge/pkg/message/rfc5322/parser"
|
|
||||||
"github.com/antlr/antlr4/runtime/Go/antlr"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ParseAddressList parses one or more valid RFC5322 (with RFC2047) addresses.
|
|
||||||
func ParseAddressList(input string) ([]*mail.Address, error) {
|
|
||||||
if len(input) == 0 {
|
|
||||||
return []*mail.Address{}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
l := parser.NewRFC5322Lexer(antlr.NewInputStream(input))
|
|
||||||
p := parser.NewRFC5322Parser(antlr.NewCommonTokenStream(l, antlr.TokenDefaultChannel))
|
|
||||||
w := &walker{}
|
|
||||||
|
|
||||||
p.AddErrorListener(w)
|
|
||||||
p.AddParseListener(&parseListener{rules: p.GetRuleNames()})
|
|
||||||
|
|
||||||
antlr.ParseTreeWalkerDefault.Walk(w, p.AddressList())
|
|
||||||
|
|
||||||
return w.res.([]*mail.Address), w.err
|
|
||||||
}
|
|
||||||
|
|
||||||
// ParseDateTime parses a valid RFC5322 date-time.
|
|
||||||
func ParseDateTime(input string) (time.Time, error) {
|
|
||||||
if len(input) == 0 {
|
|
||||||
return time.Time{}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
l := parser.NewRFC5322Lexer(antlr.NewInputStream(input))
|
|
||||||
p := parser.NewRFC5322Parser(antlr.NewCommonTokenStream(l, antlr.TokenDefaultChannel))
|
|
||||||
w := &walker{}
|
|
||||||
|
|
||||||
p.AddErrorListener(w)
|
|
||||||
p.AddParseListener(&parseListener{rules: p.GetRuleNames()})
|
|
||||||
|
|
||||||
antlr.ParseTreeWalkerDefault.Walk(w, p.DateTime())
|
|
||||||
|
|
||||||
return w.res.(time.Time), w.err
|
|
||||||
}
|
|
||||||
|
|
||||||
type parseListener struct {
|
|
||||||
antlr.BaseParseTreeListener
|
|
||||||
|
|
||||||
rules []string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *parseListener) EnterEveryRule(ctx antlr.ParserRuleContext) {
|
|
||||||
logrus.
|
|
||||||
WithField("rule", l.rules[ctx.GetRuleIndex()]).
|
|
||||||
WithField("text", ctx.GetText()).
|
|
||||||
Trace("Entering rule")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *parseListener) ExitEveryRule(ctx antlr.ParserRuleContext) {
|
|
||||||
logrus.
|
|
||||||
WithField("rule", l.rules[ctx.GetRuleIndex()]).
|
|
||||||
WithField("text", ctx.GetText()).
|
|
||||||
Trace("Exiting rule")
|
|
||||||
}
|
|
||||||
File diff suppressed because one or more lines are too long
@ -1,110 +0,0 @@
|
|||||||
U_00=1
|
|
||||||
U_01_08=2
|
|
||||||
TAB=3
|
|
||||||
LF=4
|
|
||||||
U_0B=5
|
|
||||||
U_0C=6
|
|
||||||
CR=7
|
|
||||||
U_0E_1F=8
|
|
||||||
SP=9
|
|
||||||
Exclamation=10
|
|
||||||
DQuote=11
|
|
||||||
Hash=12
|
|
||||||
Dollar=13
|
|
||||||
Percent=14
|
|
||||||
Ampersand=15
|
|
||||||
SQuote=16
|
|
||||||
LParens=17
|
|
||||||
RParens=18
|
|
||||||
Asterisk=19
|
|
||||||
Plus=20
|
|
||||||
Comma=21
|
|
||||||
Minus=22
|
|
||||||
Period=23
|
|
||||||
Slash=24
|
|
||||||
Digit=25
|
|
||||||
Colon=26
|
|
||||||
Semicolon=27
|
|
||||||
Less=28
|
|
||||||
Equal=29
|
|
||||||
Greater=30
|
|
||||||
Question=31
|
|
||||||
At=32
|
|
||||||
LBracket=33
|
|
||||||
Backslash=34
|
|
||||||
RBracket=35
|
|
||||||
Caret=36
|
|
||||||
Underscore=37
|
|
||||||
Backtick=38
|
|
||||||
LCurly=39
|
|
||||||
Pipe=40
|
|
||||||
RCurly=41
|
|
||||||
Tilde=42
|
|
||||||
Delete=43
|
|
||||||
UTF8NonAscii=44
|
|
||||||
A=45
|
|
||||||
B=46
|
|
||||||
C=47
|
|
||||||
D=48
|
|
||||||
E=49
|
|
||||||
F=50
|
|
||||||
G=51
|
|
||||||
H=52
|
|
||||||
I=53
|
|
||||||
J=54
|
|
||||||
K=55
|
|
||||||
L=56
|
|
||||||
M=57
|
|
||||||
N=58
|
|
||||||
O=59
|
|
||||||
P=60
|
|
||||||
Q=61
|
|
||||||
R=62
|
|
||||||
S=63
|
|
||||||
T=64
|
|
||||||
U=65
|
|
||||||
V=66
|
|
||||||
W=67
|
|
||||||
X=68
|
|
||||||
Y=69
|
|
||||||
Z=70
|
|
||||||
'\u0000'=1
|
|
||||||
'\t'=3
|
|
||||||
'\n'=4
|
|
||||||
'\u000B'=5
|
|
||||||
'\u000C'=6
|
|
||||||
'\r'=7
|
|
||||||
' '=9
|
|
||||||
'!'=10
|
|
||||||
'"'=11
|
|
||||||
'#'=12
|
|
||||||
'$'=13
|
|
||||||
'%'=14
|
|
||||||
'&'=15
|
|
||||||
'\''=16
|
|
||||||
'('=17
|
|
||||||
')'=18
|
|
||||||
'*'=19
|
|
||||||
'+'=20
|
|
||||||
','=21
|
|
||||||
'-'=22
|
|
||||||
'.'=23
|
|
||||||
'/'=24
|
|
||||||
':'=26
|
|
||||||
';'=27
|
|
||||||
'<'=28
|
|
||||||
'='=29
|
|
||||||
'>'=30
|
|
||||||
'?'=31
|
|
||||||
'@'=32
|
|
||||||
'['=33
|
|
||||||
'\\'=34
|
|
||||||
']'=35
|
|
||||||
'^'=36
|
|
||||||
'_'=37
|
|
||||||
'`'=38
|
|
||||||
'{'=39
|
|
||||||
'|'=40
|
|
||||||
'}'=41
|
|
||||||
'~'=42
|
|
||||||
'\u007F'=43
|
|
||||||
File diff suppressed because one or more lines are too long
@ -1,110 +0,0 @@
|
|||||||
U_00=1
|
|
||||||
U_01_08=2
|
|
||||||
TAB=3
|
|
||||||
LF=4
|
|
||||||
U_0B=5
|
|
||||||
U_0C=6
|
|
||||||
CR=7
|
|
||||||
U_0E_1F=8
|
|
||||||
SP=9
|
|
||||||
Exclamation=10
|
|
||||||
DQuote=11
|
|
||||||
Hash=12
|
|
||||||
Dollar=13
|
|
||||||
Percent=14
|
|
||||||
Ampersand=15
|
|
||||||
SQuote=16
|
|
||||||
LParens=17
|
|
||||||
RParens=18
|
|
||||||
Asterisk=19
|
|
||||||
Plus=20
|
|
||||||
Comma=21
|
|
||||||
Minus=22
|
|
||||||
Period=23
|
|
||||||
Slash=24
|
|
||||||
Digit=25
|
|
||||||
Colon=26
|
|
||||||
Semicolon=27
|
|
||||||
Less=28
|
|
||||||
Equal=29
|
|
||||||
Greater=30
|
|
||||||
Question=31
|
|
||||||
At=32
|
|
||||||
LBracket=33
|
|
||||||
Backslash=34
|
|
||||||
RBracket=35
|
|
||||||
Caret=36
|
|
||||||
Underscore=37
|
|
||||||
Backtick=38
|
|
||||||
LCurly=39
|
|
||||||
Pipe=40
|
|
||||||
RCurly=41
|
|
||||||
Tilde=42
|
|
||||||
Delete=43
|
|
||||||
UTF8NonAscii=44
|
|
||||||
A=45
|
|
||||||
B=46
|
|
||||||
C=47
|
|
||||||
D=48
|
|
||||||
E=49
|
|
||||||
F=50
|
|
||||||
G=51
|
|
||||||
H=52
|
|
||||||
I=53
|
|
||||||
J=54
|
|
||||||
K=55
|
|
||||||
L=56
|
|
||||||
M=57
|
|
||||||
N=58
|
|
||||||
O=59
|
|
||||||
P=60
|
|
||||||
Q=61
|
|
||||||
R=62
|
|
||||||
S=63
|
|
||||||
T=64
|
|
||||||
U=65
|
|
||||||
V=66
|
|
||||||
W=67
|
|
||||||
X=68
|
|
||||||
Y=69
|
|
||||||
Z=70
|
|
||||||
'\u0000'=1
|
|
||||||
'\t'=3
|
|
||||||
'\n'=4
|
|
||||||
'\u000B'=5
|
|
||||||
'\u000C'=6
|
|
||||||
'\r'=7
|
|
||||||
' '=9
|
|
||||||
'!'=10
|
|
||||||
'"'=11
|
|
||||||
'#'=12
|
|
||||||
'$'=13
|
|
||||||
'%'=14
|
|
||||||
'&'=15
|
|
||||||
'\''=16
|
|
||||||
'('=17
|
|
||||||
')'=18
|
|
||||||
'*'=19
|
|
||||||
'+'=20
|
|
||||||
','=21
|
|
||||||
'-'=22
|
|
||||||
'.'=23
|
|
||||||
'/'=24
|
|
||||||
':'=26
|
|
||||||
';'=27
|
|
||||||
'<'=28
|
|
||||||
'='=29
|
|
||||||
'>'=30
|
|
||||||
'?'=31
|
|
||||||
'@'=32
|
|
||||||
'['=33
|
|
||||||
'\\'=34
|
|
||||||
']'=35
|
|
||||||
'^'=36
|
|
||||||
'_'=37
|
|
||||||
'`'=38
|
|
||||||
'{'=39
|
|
||||||
'|'=40
|
|
||||||
'}'=41
|
|
||||||
'~'=42
|
|
||||||
'\u007F'=43
|
|
||||||
@ -1,309 +0,0 @@
|
|||||||
// Copyright (c) 2020 Proton Technologies AG
|
|
||||||
//
|
|
||||||
// This file is part of ProtonMail Bridge.
|
|
||||||
//
|
|
||||||
// ProtonMail 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.
|
|
||||||
//
|
|
||||||
// ProtonMail 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 ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
// Code generated from RFC5322Lexer.g4 by ANTLR 4.8. DO NOT EDIT.
|
|
||||||
|
|
||||||
package parser
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"unicode"
|
|
||||||
|
|
||||||
"github.com/antlr/antlr4/runtime/Go/antlr"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Suppress unused import error
|
|
||||||
var _ = fmt.Printf
|
|
||||||
var _ = unicode.IsLetter
|
|
||||||
|
|
||||||
var serializedLexerAtn = []uint16{
|
|
||||||
3, 24715, 42794, 33075, 47597, 16764, 15335, 30598, 22884, 2, 72, 283,
|
|
||||||
8, 1, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7,
|
|
||||||
9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12,
|
|
||||||
4, 13, 9, 13, 4, 14, 9, 14, 4, 15, 9, 15, 4, 16, 9, 16, 4, 17, 9, 17, 4,
|
|
||||||
18, 9, 18, 4, 19, 9, 19, 4, 20, 9, 20, 4, 21, 9, 21, 4, 22, 9, 22, 4, 23,
|
|
||||||
9, 23, 4, 24, 9, 24, 4, 25, 9, 25, 4, 26, 9, 26, 4, 27, 9, 27, 4, 28, 9,
|
|
||||||
28, 4, 29, 9, 29, 4, 30, 9, 30, 4, 31, 9, 31, 4, 32, 9, 32, 4, 33, 9, 33,
|
|
||||||
4, 34, 9, 34, 4, 35, 9, 35, 4, 36, 9, 36, 4, 37, 9, 37, 4, 38, 9, 38, 4,
|
|
||||||
39, 9, 39, 4, 40, 9, 40, 4, 41, 9, 41, 4, 42, 9, 42, 4, 43, 9, 43, 4, 44,
|
|
||||||
9, 44, 4, 45, 9, 45, 4, 46, 9, 46, 4, 47, 9, 47, 4, 48, 9, 48, 4, 49, 9,
|
|
||||||
49, 4, 50, 9, 50, 4, 51, 9, 51, 4, 52, 9, 52, 4, 53, 9, 53, 4, 54, 9, 54,
|
|
||||||
4, 55, 9, 55, 4, 56, 9, 56, 4, 57, 9, 57, 4, 58, 9, 58, 4, 59, 9, 59, 4,
|
|
||||||
60, 9, 60, 4, 61, 9, 61, 4, 62, 9, 62, 4, 63, 9, 63, 4, 64, 9, 64, 4, 65,
|
|
||||||
9, 65, 4, 66, 9, 66, 4, 67, 9, 67, 4, 68, 9, 68, 4, 69, 9, 69, 4, 70, 9,
|
|
||||||
70, 4, 71, 9, 71, 3, 2, 3, 2, 3, 3, 3, 3, 3, 4, 3, 4, 3, 5, 3, 5, 3, 6,
|
|
||||||
3, 6, 3, 7, 3, 7, 3, 8, 3, 8, 3, 9, 3, 9, 3, 10, 3, 10, 3, 11, 3, 11, 3,
|
|
||||||
12, 3, 12, 3, 13, 3, 13, 3, 14, 3, 14, 3, 15, 3, 15, 3, 16, 3, 16, 3, 17,
|
|
||||||
3, 17, 3, 18, 3, 18, 3, 19, 3, 19, 3, 20, 3, 20, 3, 21, 3, 21, 3, 22, 3,
|
|
||||||
22, 3, 23, 3, 23, 3, 24, 3, 24, 3, 25, 3, 25, 3, 26, 3, 26, 3, 27, 3, 27,
|
|
||||||
3, 28, 3, 28, 3, 29, 3, 29, 3, 30, 3, 30, 3, 31, 3, 31, 3, 32, 3, 32, 3,
|
|
||||||
33, 3, 33, 3, 34, 3, 34, 3, 35, 3, 35, 3, 36, 3, 36, 3, 37, 3, 37, 3, 38,
|
|
||||||
3, 38, 3, 39, 3, 39, 3, 40, 3, 40, 3, 41, 3, 41, 3, 42, 3, 42, 3, 43, 3,
|
|
||||||
43, 3, 44, 3, 44, 3, 45, 3, 45, 3, 46, 3, 46, 3, 47, 3, 47, 3, 48, 3, 48,
|
|
||||||
3, 49, 3, 49, 3, 50, 3, 50, 3, 51, 3, 51, 3, 52, 3, 52, 3, 53, 3, 53, 3,
|
|
||||||
54, 3, 54, 3, 55, 3, 55, 3, 56, 3, 56, 3, 57, 3, 57, 3, 58, 3, 58, 3, 59,
|
|
||||||
3, 59, 3, 60, 3, 60, 3, 61, 3, 61, 3, 62, 3, 62, 3, 63, 3, 63, 3, 64, 3,
|
|
||||||
64, 3, 65, 3, 65, 3, 66, 3, 66, 3, 67, 3, 67, 3, 68, 3, 68, 3, 69, 3, 69,
|
|
||||||
3, 70, 3, 70, 3, 71, 3, 71, 2, 2, 72, 3, 3, 5, 4, 7, 5, 9, 6, 11, 7, 13,
|
|
||||||
8, 15, 9, 17, 10, 19, 11, 21, 12, 23, 13, 25, 14, 27, 15, 29, 16, 31, 17,
|
|
||||||
33, 18, 35, 19, 37, 20, 39, 21, 41, 22, 43, 23, 45, 24, 47, 25, 49, 26,
|
|
||||||
51, 27, 53, 28, 55, 29, 57, 30, 59, 31, 61, 32, 63, 33, 65, 34, 67, 35,
|
|
||||||
69, 36, 71, 37, 73, 38, 75, 39, 77, 40, 79, 41, 81, 42, 83, 43, 85, 44,
|
|
||||||
87, 45, 89, 46, 91, 47, 93, 48, 95, 49, 97, 50, 99, 51, 101, 52, 103, 53,
|
|
||||||
105, 54, 107, 55, 109, 56, 111, 57, 113, 58, 115, 59, 117, 60, 119, 61,
|
|
||||||
121, 62, 123, 63, 125, 64, 127, 65, 129, 66, 131, 67, 133, 68, 135, 69,
|
|
||||||
137, 70, 139, 71, 141, 72, 3, 2, 29, 3, 2, 50, 59, 4, 2, 67, 67, 99, 99,
|
|
||||||
4, 2, 68, 68, 100, 100, 4, 2, 69, 69, 101, 101, 4, 2, 70, 70, 102, 102,
|
|
||||||
4, 2, 71, 71, 103, 103, 4, 2, 72, 72, 104, 104, 4, 2, 73, 73, 105, 105,
|
|
||||||
4, 2, 74, 74, 106, 106, 4, 2, 75, 75, 107, 107, 4, 2, 76, 76, 108, 108,
|
|
||||||
4, 2, 77, 77, 109, 109, 4, 2, 78, 78, 110, 110, 4, 2, 79, 79, 111, 111,
|
|
||||||
4, 2, 80, 80, 112, 112, 4, 2, 81, 81, 113, 113, 4, 2, 82, 82, 114, 114,
|
|
||||||
4, 2, 83, 83, 115, 115, 4, 2, 84, 84, 116, 116, 4, 2, 85, 85, 117, 117,
|
|
||||||
4, 2, 86, 86, 118, 118, 4, 2, 87, 87, 119, 119, 4, 2, 88, 88, 120, 120,
|
|
||||||
4, 2, 89, 89, 121, 121, 4, 2, 90, 90, 122, 122, 4, 2, 91, 91, 123, 123,
|
|
||||||
4, 2, 92, 92, 124, 124, 2, 282, 2, 3, 3, 2, 2, 2, 2, 5, 3, 2, 2, 2, 2,
|
|
||||||
7, 3, 2, 2, 2, 2, 9, 3, 2, 2, 2, 2, 11, 3, 2, 2, 2, 2, 13, 3, 2, 2, 2,
|
|
||||||
2, 15, 3, 2, 2, 2, 2, 17, 3, 2, 2, 2, 2, 19, 3, 2, 2, 2, 2, 21, 3, 2, 2,
|
|
||||||
2, 2, 23, 3, 2, 2, 2, 2, 25, 3, 2, 2, 2, 2, 27, 3, 2, 2, 2, 2, 29, 3, 2,
|
|
||||||
2, 2, 2, 31, 3, 2, 2, 2, 2, 33, 3, 2, 2, 2, 2, 35, 3, 2, 2, 2, 2, 37, 3,
|
|
||||||
2, 2, 2, 2, 39, 3, 2, 2, 2, 2, 41, 3, 2, 2, 2, 2, 43, 3, 2, 2, 2, 2, 45,
|
|
||||||
3, 2, 2, 2, 2, 47, 3, 2, 2, 2, 2, 49, 3, 2, 2, 2, 2, 51, 3, 2, 2, 2, 2,
|
|
||||||
53, 3, 2, 2, 2, 2, 55, 3, 2, 2, 2, 2, 57, 3, 2, 2, 2, 2, 59, 3, 2, 2, 2,
|
|
||||||
2, 61, 3, 2, 2, 2, 2, 63, 3, 2, 2, 2, 2, 65, 3, 2, 2, 2, 2, 67, 3, 2, 2,
|
|
||||||
2, 2, 69, 3, 2, 2, 2, 2, 71, 3, 2, 2, 2, 2, 73, 3, 2, 2, 2, 2, 75, 3, 2,
|
|
||||||
2, 2, 2, 77, 3, 2, 2, 2, 2, 79, 3, 2, 2, 2, 2, 81, 3, 2, 2, 2, 2, 83, 3,
|
|
||||||
2, 2, 2, 2, 85, 3, 2, 2, 2, 2, 87, 3, 2, 2, 2, 2, 89, 3, 2, 2, 2, 2, 91,
|
|
||||||
3, 2, 2, 2, 2, 93, 3, 2, 2, 2, 2, 95, 3, 2, 2, 2, 2, 97, 3, 2, 2, 2, 2,
|
|
||||||
99, 3, 2, 2, 2, 2, 101, 3, 2, 2, 2, 2, 103, 3, 2, 2, 2, 2, 105, 3, 2, 2,
|
|
||||||
2, 2, 107, 3, 2, 2, 2, 2, 109, 3, 2, 2, 2, 2, 111, 3, 2, 2, 2, 2, 113,
|
|
||||||
3, 2, 2, 2, 2, 115, 3, 2, 2, 2, 2, 117, 3, 2, 2, 2, 2, 119, 3, 2, 2, 2,
|
|
||||||
2, 121, 3, 2, 2, 2, 2, 123, 3, 2, 2, 2, 2, 125, 3, 2, 2, 2, 2, 127, 3,
|
|
||||||
2, 2, 2, 2, 129, 3, 2, 2, 2, 2, 131, 3, 2, 2, 2, 2, 133, 3, 2, 2, 2, 2,
|
|
||||||
135, 3, 2, 2, 2, 2, 137, 3, 2, 2, 2, 2, 139, 3, 2, 2, 2, 2, 141, 3, 2,
|
|
||||||
2, 2, 3, 143, 3, 2, 2, 2, 5, 145, 3, 2, 2, 2, 7, 147, 3, 2, 2, 2, 9, 149,
|
|
||||||
3, 2, 2, 2, 11, 151, 3, 2, 2, 2, 13, 153, 3, 2, 2, 2, 15, 155, 3, 2, 2,
|
|
||||||
2, 17, 157, 3, 2, 2, 2, 19, 159, 3, 2, 2, 2, 21, 161, 3, 2, 2, 2, 23, 163,
|
|
||||||
3, 2, 2, 2, 25, 165, 3, 2, 2, 2, 27, 167, 3, 2, 2, 2, 29, 169, 3, 2, 2,
|
|
||||||
2, 31, 171, 3, 2, 2, 2, 33, 173, 3, 2, 2, 2, 35, 175, 3, 2, 2, 2, 37, 177,
|
|
||||||
3, 2, 2, 2, 39, 179, 3, 2, 2, 2, 41, 181, 3, 2, 2, 2, 43, 183, 3, 2, 2,
|
|
||||||
2, 45, 185, 3, 2, 2, 2, 47, 187, 3, 2, 2, 2, 49, 189, 3, 2, 2, 2, 51, 191,
|
|
||||||
3, 2, 2, 2, 53, 193, 3, 2, 2, 2, 55, 195, 3, 2, 2, 2, 57, 197, 3, 2, 2,
|
|
||||||
2, 59, 199, 3, 2, 2, 2, 61, 201, 3, 2, 2, 2, 63, 203, 3, 2, 2, 2, 65, 205,
|
|
||||||
3, 2, 2, 2, 67, 207, 3, 2, 2, 2, 69, 209, 3, 2, 2, 2, 71, 211, 3, 2, 2,
|
|
||||||
2, 73, 213, 3, 2, 2, 2, 75, 215, 3, 2, 2, 2, 77, 217, 3, 2, 2, 2, 79, 219,
|
|
||||||
3, 2, 2, 2, 81, 221, 3, 2, 2, 2, 83, 223, 3, 2, 2, 2, 85, 225, 3, 2, 2,
|
|
||||||
2, 87, 227, 3, 2, 2, 2, 89, 229, 3, 2, 2, 2, 91, 231, 3, 2, 2, 2, 93, 233,
|
|
||||||
3, 2, 2, 2, 95, 235, 3, 2, 2, 2, 97, 237, 3, 2, 2, 2, 99, 239, 3, 2, 2,
|
|
||||||
2, 101, 241, 3, 2, 2, 2, 103, 243, 3, 2, 2, 2, 105, 245, 3, 2, 2, 2, 107,
|
|
||||||
247, 3, 2, 2, 2, 109, 249, 3, 2, 2, 2, 111, 251, 3, 2, 2, 2, 113, 253,
|
|
||||||
3, 2, 2, 2, 115, 255, 3, 2, 2, 2, 117, 257, 3, 2, 2, 2, 119, 259, 3, 2,
|
|
||||||
2, 2, 121, 261, 3, 2, 2, 2, 123, 263, 3, 2, 2, 2, 125, 265, 3, 2, 2, 2,
|
|
||||||
127, 267, 3, 2, 2, 2, 129, 269, 3, 2, 2, 2, 131, 271, 3, 2, 2, 2, 133,
|
|
||||||
273, 3, 2, 2, 2, 135, 275, 3, 2, 2, 2, 137, 277, 3, 2, 2, 2, 139, 279,
|
|
||||||
3, 2, 2, 2, 141, 281, 3, 2, 2, 2, 143, 144, 7, 2, 2, 2, 144, 4, 3, 2, 2,
|
|
||||||
2, 145, 146, 4, 3, 10, 2, 146, 6, 3, 2, 2, 2, 147, 148, 7, 11, 2, 2, 148,
|
|
||||||
8, 3, 2, 2, 2, 149, 150, 7, 12, 2, 2, 150, 10, 3, 2, 2, 2, 151, 152, 7,
|
|
||||||
13, 2, 2, 152, 12, 3, 2, 2, 2, 153, 154, 7, 14, 2, 2, 154, 14, 3, 2, 2,
|
|
||||||
2, 155, 156, 7, 15, 2, 2, 156, 16, 3, 2, 2, 2, 157, 158, 4, 16, 33, 2,
|
|
||||||
158, 18, 3, 2, 2, 2, 159, 160, 7, 34, 2, 2, 160, 20, 3, 2, 2, 2, 161, 162,
|
|
||||||
7, 35, 2, 2, 162, 22, 3, 2, 2, 2, 163, 164, 7, 36, 2, 2, 164, 24, 3, 2,
|
|
||||||
2, 2, 165, 166, 7, 37, 2, 2, 166, 26, 3, 2, 2, 2, 167, 168, 7, 38, 2, 2,
|
|
||||||
168, 28, 3, 2, 2, 2, 169, 170, 7, 39, 2, 2, 170, 30, 3, 2, 2, 2, 171, 172,
|
|
||||||
7, 40, 2, 2, 172, 32, 3, 2, 2, 2, 173, 174, 7, 41, 2, 2, 174, 34, 3, 2,
|
|
||||||
2, 2, 175, 176, 7, 42, 2, 2, 176, 36, 3, 2, 2, 2, 177, 178, 7, 43, 2, 2,
|
|
||||||
178, 38, 3, 2, 2, 2, 179, 180, 7, 44, 2, 2, 180, 40, 3, 2, 2, 2, 181, 182,
|
|
||||||
7, 45, 2, 2, 182, 42, 3, 2, 2, 2, 183, 184, 7, 46, 2, 2, 184, 44, 3, 2,
|
|
||||||
2, 2, 185, 186, 7, 47, 2, 2, 186, 46, 3, 2, 2, 2, 187, 188, 7, 48, 2, 2,
|
|
||||||
188, 48, 3, 2, 2, 2, 189, 190, 7, 49, 2, 2, 190, 50, 3, 2, 2, 2, 191, 192,
|
|
||||||
9, 2, 2, 2, 192, 52, 3, 2, 2, 2, 193, 194, 7, 60, 2, 2, 194, 54, 3, 2,
|
|
||||||
2, 2, 195, 196, 7, 61, 2, 2, 196, 56, 3, 2, 2, 2, 197, 198, 7, 62, 2, 2,
|
|
||||||
198, 58, 3, 2, 2, 2, 199, 200, 7, 63, 2, 2, 200, 60, 3, 2, 2, 2, 201, 202,
|
|
||||||
7, 64, 2, 2, 202, 62, 3, 2, 2, 2, 203, 204, 7, 65, 2, 2, 204, 64, 3, 2,
|
|
||||||
2, 2, 205, 206, 7, 66, 2, 2, 206, 66, 3, 2, 2, 2, 207, 208, 7, 93, 2, 2,
|
|
||||||
208, 68, 3, 2, 2, 2, 209, 210, 7, 94, 2, 2, 210, 70, 3, 2, 2, 2, 211, 212,
|
|
||||||
7, 95, 2, 2, 212, 72, 3, 2, 2, 2, 213, 214, 7, 96, 2, 2, 214, 74, 3, 2,
|
|
||||||
2, 2, 215, 216, 7, 97, 2, 2, 216, 76, 3, 2, 2, 2, 217, 218, 7, 98, 2, 2,
|
|
||||||
218, 78, 3, 2, 2, 2, 219, 220, 7, 125, 2, 2, 220, 80, 3, 2, 2, 2, 221,
|
|
||||||
222, 7, 126, 2, 2, 222, 82, 3, 2, 2, 2, 223, 224, 7, 127, 2, 2, 224, 84,
|
|
||||||
3, 2, 2, 2, 225, 226, 7, 128, 2, 2, 226, 86, 3, 2, 2, 2, 227, 228, 7, 129,
|
|
||||||
2, 2, 228, 88, 3, 2, 2, 2, 229, 230, 4, 130, 1, 2, 230, 90, 3, 2, 2, 2,
|
|
||||||
231, 232, 9, 3, 2, 2, 232, 92, 3, 2, 2, 2, 233, 234, 9, 4, 2, 2, 234, 94,
|
|
||||||
3, 2, 2, 2, 235, 236, 9, 5, 2, 2, 236, 96, 3, 2, 2, 2, 237, 238, 9, 6,
|
|
||||||
2, 2, 238, 98, 3, 2, 2, 2, 239, 240, 9, 7, 2, 2, 240, 100, 3, 2, 2, 2,
|
|
||||||
241, 242, 9, 8, 2, 2, 242, 102, 3, 2, 2, 2, 243, 244, 9, 9, 2, 2, 244,
|
|
||||||
104, 3, 2, 2, 2, 245, 246, 9, 10, 2, 2, 246, 106, 3, 2, 2, 2, 247, 248,
|
|
||||||
9, 11, 2, 2, 248, 108, 3, 2, 2, 2, 249, 250, 9, 12, 2, 2, 250, 110, 3,
|
|
||||||
2, 2, 2, 251, 252, 9, 13, 2, 2, 252, 112, 3, 2, 2, 2, 253, 254, 9, 14,
|
|
||||||
2, 2, 254, 114, 3, 2, 2, 2, 255, 256, 9, 15, 2, 2, 256, 116, 3, 2, 2, 2,
|
|
||||||
257, 258, 9, 16, 2, 2, 258, 118, 3, 2, 2, 2, 259, 260, 9, 17, 2, 2, 260,
|
|
||||||
120, 3, 2, 2, 2, 261, 262, 9, 18, 2, 2, 262, 122, 3, 2, 2, 2, 263, 264,
|
|
||||||
9, 19, 2, 2, 264, 124, 3, 2, 2, 2, 265, 266, 9, 20, 2, 2, 266, 126, 3,
|
|
||||||
2, 2, 2, 267, 268, 9, 21, 2, 2, 268, 128, 3, 2, 2, 2, 269, 270, 9, 22,
|
|
||||||
2, 2, 270, 130, 3, 2, 2, 2, 271, 272, 9, 23, 2, 2, 272, 132, 3, 2, 2, 2,
|
|
||||||
273, 274, 9, 24, 2, 2, 274, 134, 3, 2, 2, 2, 275, 276, 9, 25, 2, 2, 276,
|
|
||||||
136, 3, 2, 2, 2, 277, 278, 9, 26, 2, 2, 278, 138, 3, 2, 2, 2, 279, 280,
|
|
||||||
9, 27, 2, 2, 280, 140, 3, 2, 2, 2, 281, 282, 9, 28, 2, 2, 282, 142, 3,
|
|
||||||
2, 2, 2, 3, 2, 2,
|
|
||||||
}
|
|
||||||
|
|
||||||
var lexerDeserializer = antlr.NewATNDeserializer(nil)
|
|
||||||
var lexerAtn = lexerDeserializer.DeserializeFromUInt16(serializedLexerAtn)
|
|
||||||
|
|
||||||
var lexerChannelNames = []string{
|
|
||||||
"DEFAULT_TOKEN_CHANNEL", "HIDDEN",
|
|
||||||
}
|
|
||||||
|
|
||||||
var lexerModeNames = []string{
|
|
||||||
"DEFAULT_MODE",
|
|
||||||
}
|
|
||||||
|
|
||||||
var lexerLiteralNames = []string{
|
|
||||||
"", "'\u0000'", "", "'\t'", "'\n'", "'\u000B'", "'\u000C'", "'\r'", "",
|
|
||||||
"' '", "'!'", "'\"'", "'#'", "'$'", "'%'", "'&'", "'''", "'('", "')'",
|
|
||||||
"'*'", "'+'", "','", "'-'", "'.'", "'/'", "", "':'", "';'", "'<'", "'='",
|
|
||||||
"'>'", "'?'", "'@'", "'['", "'\\'", "']'", "'^'", "'_'", "'`'", "'{'",
|
|
||||||
"'|'", "'}'", "'~'", "'\u007F'",
|
|
||||||
}
|
|
||||||
|
|
||||||
var lexerSymbolicNames = []string{
|
|
||||||
"", "U_00", "U_01_08", "TAB", "LF", "U_0B", "U_0C", "CR", "U_0E_1F", "SP",
|
|
||||||
"Exclamation", "DQuote", "Hash", "Dollar", "Percent", "Ampersand", "SQuote",
|
|
||||||
"LParens", "RParens", "Asterisk", "Plus", "Comma", "Minus", "Period", "Slash",
|
|
||||||
"Digit", "Colon", "Semicolon", "Less", "Equal", "Greater", "Question",
|
|
||||||
"At", "LBracket", "Backslash", "RBracket", "Caret", "Underscore", "Backtick",
|
|
||||||
"LCurly", "Pipe", "RCurly", "Tilde", "Delete", "UTF8NonAscii", "A", "B",
|
|
||||||
"C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q",
|
|
||||||
"R", "S", "T", "U", "V", "W", "X", "Y", "Z",
|
|
||||||
}
|
|
||||||
|
|
||||||
var lexerRuleNames = []string{
|
|
||||||
"U_00", "U_01_08", "TAB", "LF", "U_0B", "U_0C", "CR", "U_0E_1F", "SP",
|
|
||||||
"Exclamation", "DQuote", "Hash", "Dollar", "Percent", "Ampersand", "SQuote",
|
|
||||||
"LParens", "RParens", "Asterisk", "Plus", "Comma", "Minus", "Period", "Slash",
|
|
||||||
"Digit", "Colon", "Semicolon", "Less", "Equal", "Greater", "Question",
|
|
||||||
"At", "LBracket", "Backslash", "RBracket", "Caret", "Underscore", "Backtick",
|
|
||||||
"LCurly", "Pipe", "RCurly", "Tilde", "Delete", "UTF8NonAscii", "A", "B",
|
|
||||||
"C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q",
|
|
||||||
"R", "S", "T", "U", "V", "W", "X", "Y", "Z",
|
|
||||||
}
|
|
||||||
|
|
||||||
type RFC5322Lexer struct {
|
|
||||||
*antlr.BaseLexer
|
|
||||||
channelNames []string
|
|
||||||
modeNames []string
|
|
||||||
// TODO: EOF string
|
|
||||||
}
|
|
||||||
|
|
||||||
var lexerDecisionToDFA = make([]*antlr.DFA, len(lexerAtn.DecisionToState))
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
for index, ds := range lexerAtn.DecisionToState {
|
|
||||||
lexerDecisionToDFA[index] = antlr.NewDFA(ds, index)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewRFC5322Lexer(input antlr.CharStream) *RFC5322Lexer {
|
|
||||||
|
|
||||||
l := new(RFC5322Lexer)
|
|
||||||
|
|
||||||
l.BaseLexer = antlr.NewBaseLexer(input)
|
|
||||||
l.Interpreter = antlr.NewLexerATNSimulator(l, lexerAtn, lexerDecisionToDFA, antlr.NewPredictionContextCache())
|
|
||||||
|
|
||||||
l.channelNames = lexerChannelNames
|
|
||||||
l.modeNames = lexerModeNames
|
|
||||||
l.RuleNames = lexerRuleNames
|
|
||||||
l.LiteralNames = lexerLiteralNames
|
|
||||||
l.SymbolicNames = lexerSymbolicNames
|
|
||||||
l.GrammarFileName = "RFC5322Lexer.g4"
|
|
||||||
// TODO: l.EOF = antlr.TokenEOF
|
|
||||||
|
|
||||||
return l
|
|
||||||
}
|
|
||||||
|
|
||||||
// RFC5322Lexer tokens.
|
|
||||||
const (
|
|
||||||
RFC5322LexerU_00 = 1
|
|
||||||
RFC5322LexerU_01_08 = 2
|
|
||||||
RFC5322LexerTAB = 3
|
|
||||||
RFC5322LexerLF = 4
|
|
||||||
RFC5322LexerU_0B = 5
|
|
||||||
RFC5322LexerU_0C = 6
|
|
||||||
RFC5322LexerCR = 7
|
|
||||||
RFC5322LexerU_0E_1F = 8
|
|
||||||
RFC5322LexerSP = 9
|
|
||||||
RFC5322LexerExclamation = 10
|
|
||||||
RFC5322LexerDQuote = 11
|
|
||||||
RFC5322LexerHash = 12
|
|
||||||
RFC5322LexerDollar = 13
|
|
||||||
RFC5322LexerPercent = 14
|
|
||||||
RFC5322LexerAmpersand = 15
|
|
||||||
RFC5322LexerSQuote = 16
|
|
||||||
RFC5322LexerLParens = 17
|
|
||||||
RFC5322LexerRParens = 18
|
|
||||||
RFC5322LexerAsterisk = 19
|
|
||||||
RFC5322LexerPlus = 20
|
|
||||||
RFC5322LexerComma = 21
|
|
||||||
RFC5322LexerMinus = 22
|
|
||||||
RFC5322LexerPeriod = 23
|
|
||||||
RFC5322LexerSlash = 24
|
|
||||||
RFC5322LexerDigit = 25
|
|
||||||
RFC5322LexerColon = 26
|
|
||||||
RFC5322LexerSemicolon = 27
|
|
||||||
RFC5322LexerLess = 28
|
|
||||||
RFC5322LexerEqual = 29
|
|
||||||
RFC5322LexerGreater = 30
|
|
||||||
RFC5322LexerQuestion = 31
|
|
||||||
RFC5322LexerAt = 32
|
|
||||||
RFC5322LexerLBracket = 33
|
|
||||||
RFC5322LexerBackslash = 34
|
|
||||||
RFC5322LexerRBracket = 35
|
|
||||||
RFC5322LexerCaret = 36
|
|
||||||
RFC5322LexerUnderscore = 37
|
|
||||||
RFC5322LexerBacktick = 38
|
|
||||||
RFC5322LexerLCurly = 39
|
|
||||||
RFC5322LexerPipe = 40
|
|
||||||
RFC5322LexerRCurly = 41
|
|
||||||
RFC5322LexerTilde = 42
|
|
||||||
RFC5322LexerDelete = 43
|
|
||||||
RFC5322LexerUTF8NonAscii = 44
|
|
||||||
RFC5322LexerA = 45
|
|
||||||
RFC5322LexerB = 46
|
|
||||||
RFC5322LexerC = 47
|
|
||||||
RFC5322LexerD = 48
|
|
||||||
RFC5322LexerE = 49
|
|
||||||
RFC5322LexerF = 50
|
|
||||||
RFC5322LexerG = 51
|
|
||||||
RFC5322LexerH = 52
|
|
||||||
RFC5322LexerI = 53
|
|
||||||
RFC5322LexerJ = 54
|
|
||||||
RFC5322LexerK = 55
|
|
||||||
RFC5322LexerL = 56
|
|
||||||
RFC5322LexerM = 57
|
|
||||||
RFC5322LexerN = 58
|
|
||||||
RFC5322LexerO = 59
|
|
||||||
RFC5322LexerP = 60
|
|
||||||
RFC5322LexerQ = 61
|
|
||||||
RFC5322LexerR = 62
|
|
||||||
RFC5322LexerS = 63
|
|
||||||
RFC5322LexerT = 64
|
|
||||||
RFC5322LexerU = 65
|
|
||||||
RFC5322LexerV = 66
|
|
||||||
RFC5322LexerW = 67
|
|
||||||
RFC5322LexerX = 68
|
|
||||||
RFC5322LexerY = 69
|
|
||||||
RFC5322LexerZ = 70
|
|
||||||
)
|
|
||||||
File diff suppressed because it is too large
Load Diff
@ -1,435 +0,0 @@
|
|||||||
// Copyright (c) 2020 Proton Technologies AG
|
|
||||||
//
|
|
||||||
// This file is part of ProtonMail Bridge.
|
|
||||||
//
|
|
||||||
// ProtonMail 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.
|
|
||||||
//
|
|
||||||
// ProtonMail 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 ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
// Code generated from RFC5322Parser.g4 by ANTLR 4.8. DO NOT EDIT.
|
|
||||||
|
|
||||||
package parser // RFC5322Parser
|
|
||||||
|
|
||||||
import "github.com/antlr/antlr4/runtime/Go/antlr"
|
|
||||||
|
|
||||||
// BaseRFC5322ParserListener is a complete listener for a parse tree produced by RFC5322Parser.
|
|
||||||
type BaseRFC5322ParserListener struct{}
|
|
||||||
|
|
||||||
var _ RFC5322ParserListener = &BaseRFC5322ParserListener{}
|
|
||||||
|
|
||||||
// VisitTerminal is called when a terminal node is visited.
|
|
||||||
func (s *BaseRFC5322ParserListener) VisitTerminal(node antlr.TerminalNode) {}
|
|
||||||
|
|
||||||
// VisitErrorNode is called when an error node is visited.
|
|
||||||
func (s *BaseRFC5322ParserListener) VisitErrorNode(node antlr.ErrorNode) {}
|
|
||||||
|
|
||||||
// EnterEveryRule is called when any rule is entered.
|
|
||||||
func (s *BaseRFC5322ParserListener) EnterEveryRule(ctx antlr.ParserRuleContext) {}
|
|
||||||
|
|
||||||
// ExitEveryRule is called when any rule is exited.
|
|
||||||
func (s *BaseRFC5322ParserListener) ExitEveryRule(ctx antlr.ParserRuleContext) {}
|
|
||||||
|
|
||||||
// EnterQuotedChar is called when production quotedChar is entered.
|
|
||||||
func (s *BaseRFC5322ParserListener) EnterQuotedChar(ctx *QuotedCharContext) {}
|
|
||||||
|
|
||||||
// ExitQuotedChar is called when production quotedChar is exited.
|
|
||||||
func (s *BaseRFC5322ParserListener) ExitQuotedChar(ctx *QuotedCharContext) {}
|
|
||||||
|
|
||||||
// EnterQuotedPair is called when production quotedPair is entered.
|
|
||||||
func (s *BaseRFC5322ParserListener) EnterQuotedPair(ctx *QuotedPairContext) {}
|
|
||||||
|
|
||||||
// ExitQuotedPair is called when production quotedPair is exited.
|
|
||||||
func (s *BaseRFC5322ParserListener) ExitQuotedPair(ctx *QuotedPairContext) {}
|
|
||||||
|
|
||||||
// EnterFws is called when production fws is entered.
|
|
||||||
func (s *BaseRFC5322ParserListener) EnterFws(ctx *FwsContext) {}
|
|
||||||
|
|
||||||
// ExitFws is called when production fws is exited.
|
|
||||||
func (s *BaseRFC5322ParserListener) ExitFws(ctx *FwsContext) {}
|
|
||||||
|
|
||||||
// EnterCtext is called when production ctext is entered.
|
|
||||||
func (s *BaseRFC5322ParserListener) EnterCtext(ctx *CtextContext) {}
|
|
||||||
|
|
||||||
// ExitCtext is called when production ctext is exited.
|
|
||||||
func (s *BaseRFC5322ParserListener) ExitCtext(ctx *CtextContext) {}
|
|
||||||
|
|
||||||
// EnterCcontent is called when production ccontent is entered.
|
|
||||||
func (s *BaseRFC5322ParserListener) EnterCcontent(ctx *CcontentContext) {}
|
|
||||||
|
|
||||||
// ExitCcontent is called when production ccontent is exited.
|
|
||||||
func (s *BaseRFC5322ParserListener) ExitCcontent(ctx *CcontentContext) {}
|
|
||||||
|
|
||||||
// EnterComment is called when production comment is entered.
|
|
||||||
func (s *BaseRFC5322ParserListener) EnterComment(ctx *CommentContext) {}
|
|
||||||
|
|
||||||
// ExitComment is called when production comment is exited.
|
|
||||||
func (s *BaseRFC5322ParserListener) ExitComment(ctx *CommentContext) {}
|
|
||||||
|
|
||||||
// EnterCfws is called when production cfws is entered.
|
|
||||||
func (s *BaseRFC5322ParserListener) EnterCfws(ctx *CfwsContext) {}
|
|
||||||
|
|
||||||
// ExitCfws is called when production cfws is exited.
|
|
||||||
func (s *BaseRFC5322ParserListener) ExitCfws(ctx *CfwsContext) {}
|
|
||||||
|
|
||||||
// EnterAtext is called when production atext is entered.
|
|
||||||
func (s *BaseRFC5322ParserListener) EnterAtext(ctx *AtextContext) {}
|
|
||||||
|
|
||||||
// ExitAtext is called when production atext is exited.
|
|
||||||
func (s *BaseRFC5322ParserListener) ExitAtext(ctx *AtextContext) {}
|
|
||||||
|
|
||||||
// EnterAtom is called when production atom is entered.
|
|
||||||
func (s *BaseRFC5322ParserListener) EnterAtom(ctx *AtomContext) {}
|
|
||||||
|
|
||||||
// ExitAtom is called when production atom is exited.
|
|
||||||
func (s *BaseRFC5322ParserListener) ExitAtom(ctx *AtomContext) {}
|
|
||||||
|
|
||||||
// EnterDotAtom is called when production dotAtom is entered.
|
|
||||||
func (s *BaseRFC5322ParserListener) EnterDotAtom(ctx *DotAtomContext) {}
|
|
||||||
|
|
||||||
// ExitDotAtom is called when production dotAtom is exited.
|
|
||||||
func (s *BaseRFC5322ParserListener) ExitDotAtom(ctx *DotAtomContext) {}
|
|
||||||
|
|
||||||
// EnterQtext is called when production qtext is entered.
|
|
||||||
func (s *BaseRFC5322ParserListener) EnterQtext(ctx *QtextContext) {}
|
|
||||||
|
|
||||||
// ExitQtext is called when production qtext is exited.
|
|
||||||
func (s *BaseRFC5322ParserListener) ExitQtext(ctx *QtextContext) {}
|
|
||||||
|
|
||||||
// EnterQuotedContent is called when production quotedContent is entered.
|
|
||||||
func (s *BaseRFC5322ParserListener) EnterQuotedContent(ctx *QuotedContentContext) {}
|
|
||||||
|
|
||||||
// ExitQuotedContent is called when production quotedContent is exited.
|
|
||||||
func (s *BaseRFC5322ParserListener) ExitQuotedContent(ctx *QuotedContentContext) {}
|
|
||||||
|
|
||||||
// EnterQuotedValue is called when production quotedValue is entered.
|
|
||||||
func (s *BaseRFC5322ParserListener) EnterQuotedValue(ctx *QuotedValueContext) {}
|
|
||||||
|
|
||||||
// ExitQuotedValue is called when production quotedValue is exited.
|
|
||||||
func (s *BaseRFC5322ParserListener) ExitQuotedValue(ctx *QuotedValueContext) {}
|
|
||||||
|
|
||||||
// EnterQuotedString is called when production quotedString is entered.
|
|
||||||
func (s *BaseRFC5322ParserListener) EnterQuotedString(ctx *QuotedStringContext) {}
|
|
||||||
|
|
||||||
// ExitQuotedString is called when production quotedString is exited.
|
|
||||||
func (s *BaseRFC5322ParserListener) ExitQuotedString(ctx *QuotedStringContext) {}
|
|
||||||
|
|
||||||
// EnterWord is called when production word is entered.
|
|
||||||
func (s *BaseRFC5322ParserListener) EnterWord(ctx *WordContext) {}
|
|
||||||
|
|
||||||
// ExitWord is called when production word is exited.
|
|
||||||
func (s *BaseRFC5322ParserListener) ExitWord(ctx *WordContext) {}
|
|
||||||
|
|
||||||
// EnterDateTime is called when production dateTime is entered.
|
|
||||||
func (s *BaseRFC5322ParserListener) EnterDateTime(ctx *DateTimeContext) {}
|
|
||||||
|
|
||||||
// ExitDateTime is called when production dateTime is exited.
|
|
||||||
func (s *BaseRFC5322ParserListener) ExitDateTime(ctx *DateTimeContext) {}
|
|
||||||
|
|
||||||
// EnterDayOfweek is called when production dayOfweek is entered.
|
|
||||||
func (s *BaseRFC5322ParserListener) EnterDayOfweek(ctx *DayOfweekContext) {}
|
|
||||||
|
|
||||||
// ExitDayOfweek is called when production dayOfweek is exited.
|
|
||||||
func (s *BaseRFC5322ParserListener) ExitDayOfweek(ctx *DayOfweekContext) {}
|
|
||||||
|
|
||||||
// EnterDayName is called when production dayName is entered.
|
|
||||||
func (s *BaseRFC5322ParserListener) EnterDayName(ctx *DayNameContext) {}
|
|
||||||
|
|
||||||
// ExitDayName is called when production dayName is exited.
|
|
||||||
func (s *BaseRFC5322ParserListener) ExitDayName(ctx *DayNameContext) {}
|
|
||||||
|
|
||||||
// EnterDay is called when production day is entered.
|
|
||||||
func (s *BaseRFC5322ParserListener) EnterDay(ctx *DayContext) {}
|
|
||||||
|
|
||||||
// ExitDay is called when production day is exited.
|
|
||||||
func (s *BaseRFC5322ParserListener) ExitDay(ctx *DayContext) {}
|
|
||||||
|
|
||||||
// EnterMonth is called when production month is entered.
|
|
||||||
func (s *BaseRFC5322ParserListener) EnterMonth(ctx *MonthContext) {}
|
|
||||||
|
|
||||||
// ExitMonth is called when production month is exited.
|
|
||||||
func (s *BaseRFC5322ParserListener) ExitMonth(ctx *MonthContext) {}
|
|
||||||
|
|
||||||
// EnterYear is called when production year is entered.
|
|
||||||
func (s *BaseRFC5322ParserListener) EnterYear(ctx *YearContext) {}
|
|
||||||
|
|
||||||
// ExitYear is called when production year is exited.
|
|
||||||
func (s *BaseRFC5322ParserListener) ExitYear(ctx *YearContext) {}
|
|
||||||
|
|
||||||
// EnterHour is called when production hour is entered.
|
|
||||||
func (s *BaseRFC5322ParserListener) EnterHour(ctx *HourContext) {}
|
|
||||||
|
|
||||||
// ExitHour is called when production hour is exited.
|
|
||||||
func (s *BaseRFC5322ParserListener) ExitHour(ctx *HourContext) {}
|
|
||||||
|
|
||||||
// EnterMinute is called when production minute is entered.
|
|
||||||
func (s *BaseRFC5322ParserListener) EnterMinute(ctx *MinuteContext) {}
|
|
||||||
|
|
||||||
// ExitMinute is called when production minute is exited.
|
|
||||||
func (s *BaseRFC5322ParserListener) ExitMinute(ctx *MinuteContext) {}
|
|
||||||
|
|
||||||
// EnterSecond is called when production second is entered.
|
|
||||||
func (s *BaseRFC5322ParserListener) EnterSecond(ctx *SecondContext) {}
|
|
||||||
|
|
||||||
// ExitSecond is called when production second is exited.
|
|
||||||
func (s *BaseRFC5322ParserListener) ExitSecond(ctx *SecondContext) {}
|
|
||||||
|
|
||||||
// EnterOffset is called when production offset is entered.
|
|
||||||
func (s *BaseRFC5322ParserListener) EnterOffset(ctx *OffsetContext) {}
|
|
||||||
|
|
||||||
// ExitOffset is called when production offset is exited.
|
|
||||||
func (s *BaseRFC5322ParserListener) ExitOffset(ctx *OffsetContext) {}
|
|
||||||
|
|
||||||
// EnterZone is called when production zone is entered.
|
|
||||||
func (s *BaseRFC5322ParserListener) EnterZone(ctx *ZoneContext) {}
|
|
||||||
|
|
||||||
// ExitZone is called when production zone is exited.
|
|
||||||
func (s *BaseRFC5322ParserListener) ExitZone(ctx *ZoneContext) {}
|
|
||||||
|
|
||||||
// EnterAddress is called when production address is entered.
|
|
||||||
func (s *BaseRFC5322ParserListener) EnterAddress(ctx *AddressContext) {}
|
|
||||||
|
|
||||||
// ExitAddress is called when production address is exited.
|
|
||||||
func (s *BaseRFC5322ParserListener) ExitAddress(ctx *AddressContext) {}
|
|
||||||
|
|
||||||
// EnterMailbox is called when production mailbox is entered.
|
|
||||||
func (s *BaseRFC5322ParserListener) EnterMailbox(ctx *MailboxContext) {}
|
|
||||||
|
|
||||||
// ExitMailbox is called when production mailbox is exited.
|
|
||||||
func (s *BaseRFC5322ParserListener) ExitMailbox(ctx *MailboxContext) {}
|
|
||||||
|
|
||||||
// EnterNameAddr is called when production nameAddr is entered.
|
|
||||||
func (s *BaseRFC5322ParserListener) EnterNameAddr(ctx *NameAddrContext) {}
|
|
||||||
|
|
||||||
// ExitNameAddr is called when production nameAddr is exited.
|
|
||||||
func (s *BaseRFC5322ParserListener) ExitNameAddr(ctx *NameAddrContext) {}
|
|
||||||
|
|
||||||
// EnterAngleAddr is called when production angleAddr is entered.
|
|
||||||
func (s *BaseRFC5322ParserListener) EnterAngleAddr(ctx *AngleAddrContext) {}
|
|
||||||
|
|
||||||
// ExitAngleAddr is called when production angleAddr is exited.
|
|
||||||
func (s *BaseRFC5322ParserListener) ExitAngleAddr(ctx *AngleAddrContext) {}
|
|
||||||
|
|
||||||
// EnterGroup is called when production group is entered.
|
|
||||||
func (s *BaseRFC5322ParserListener) EnterGroup(ctx *GroupContext) {}
|
|
||||||
|
|
||||||
// ExitGroup is called when production group is exited.
|
|
||||||
func (s *BaseRFC5322ParserListener) ExitGroup(ctx *GroupContext) {}
|
|
||||||
|
|
||||||
// EnterDisplayName is called when production displayName is entered.
|
|
||||||
func (s *BaseRFC5322ParserListener) EnterDisplayName(ctx *DisplayNameContext) {}
|
|
||||||
|
|
||||||
// ExitDisplayName is called when production displayName is exited.
|
|
||||||
func (s *BaseRFC5322ParserListener) ExitDisplayName(ctx *DisplayNameContext) {}
|
|
||||||
|
|
||||||
// EnterMailboxList is called when production mailboxList is entered.
|
|
||||||
func (s *BaseRFC5322ParserListener) EnterMailboxList(ctx *MailboxListContext) {}
|
|
||||||
|
|
||||||
// ExitMailboxList is called when production mailboxList is exited.
|
|
||||||
func (s *BaseRFC5322ParserListener) ExitMailboxList(ctx *MailboxListContext) {}
|
|
||||||
|
|
||||||
// EnterAddressList is called when production addressList is entered.
|
|
||||||
func (s *BaseRFC5322ParserListener) EnterAddressList(ctx *AddressListContext) {}
|
|
||||||
|
|
||||||
// ExitAddressList is called when production addressList is exited.
|
|
||||||
func (s *BaseRFC5322ParserListener) ExitAddressList(ctx *AddressListContext) {}
|
|
||||||
|
|
||||||
// EnterGroupList is called when production groupList is entered.
|
|
||||||
func (s *BaseRFC5322ParserListener) EnterGroupList(ctx *GroupListContext) {}
|
|
||||||
|
|
||||||
// ExitGroupList is called when production groupList is exited.
|
|
||||||
func (s *BaseRFC5322ParserListener) ExitGroupList(ctx *GroupListContext) {}
|
|
||||||
|
|
||||||
// EnterAddrSpec is called when production addrSpec is entered.
|
|
||||||
func (s *BaseRFC5322ParserListener) EnterAddrSpec(ctx *AddrSpecContext) {}
|
|
||||||
|
|
||||||
// ExitAddrSpec is called when production addrSpec is exited.
|
|
||||||
func (s *BaseRFC5322ParserListener) ExitAddrSpec(ctx *AddrSpecContext) {}
|
|
||||||
|
|
||||||
// EnterLocalPart is called when production localPart is entered.
|
|
||||||
func (s *BaseRFC5322ParserListener) EnterLocalPart(ctx *LocalPartContext) {}
|
|
||||||
|
|
||||||
// ExitLocalPart is called when production localPart is exited.
|
|
||||||
func (s *BaseRFC5322ParserListener) ExitLocalPart(ctx *LocalPartContext) {}
|
|
||||||
|
|
||||||
// EnterPort is called when production port is entered.
|
|
||||||
func (s *BaseRFC5322ParserListener) EnterPort(ctx *PortContext) {}
|
|
||||||
|
|
||||||
// ExitPort is called when production port is exited.
|
|
||||||
func (s *BaseRFC5322ParserListener) ExitPort(ctx *PortContext) {}
|
|
||||||
|
|
||||||
// EnterDomain is called when production domain is entered.
|
|
||||||
func (s *BaseRFC5322ParserListener) EnterDomain(ctx *DomainContext) {}
|
|
||||||
|
|
||||||
// ExitDomain is called when production domain is exited.
|
|
||||||
func (s *BaseRFC5322ParserListener) ExitDomain(ctx *DomainContext) {}
|
|
||||||
|
|
||||||
// EnterDomainLiteral is called when production domainLiteral is entered.
|
|
||||||
func (s *BaseRFC5322ParserListener) EnterDomainLiteral(ctx *DomainLiteralContext) {}
|
|
||||||
|
|
||||||
// ExitDomainLiteral is called when production domainLiteral is exited.
|
|
||||||
func (s *BaseRFC5322ParserListener) ExitDomainLiteral(ctx *DomainLiteralContext) {}
|
|
||||||
|
|
||||||
// EnterDtext is called when production dtext is entered.
|
|
||||||
func (s *BaseRFC5322ParserListener) EnterDtext(ctx *DtextContext) {}
|
|
||||||
|
|
||||||
// ExitDtext is called when production dtext is exited.
|
|
||||||
func (s *BaseRFC5322ParserListener) ExitDtext(ctx *DtextContext) {}
|
|
||||||
|
|
||||||
// EnterObsNoWSCTL is called when production obsNoWSCTL is entered.
|
|
||||||
func (s *BaseRFC5322ParserListener) EnterObsNoWSCTL(ctx *ObsNoWSCTLContext) {}
|
|
||||||
|
|
||||||
// ExitObsNoWSCTL is called when production obsNoWSCTL is exited.
|
|
||||||
func (s *BaseRFC5322ParserListener) ExitObsNoWSCTL(ctx *ObsNoWSCTLContext) {}
|
|
||||||
|
|
||||||
// EnterObsCtext is called when production obsCtext is entered.
|
|
||||||
func (s *BaseRFC5322ParserListener) EnterObsCtext(ctx *ObsCtextContext) {}
|
|
||||||
|
|
||||||
// ExitObsCtext is called when production obsCtext is exited.
|
|
||||||
func (s *BaseRFC5322ParserListener) ExitObsCtext(ctx *ObsCtextContext) {}
|
|
||||||
|
|
||||||
// EnterObsQtext is called when production obsQtext is entered.
|
|
||||||
func (s *BaseRFC5322ParserListener) EnterObsQtext(ctx *ObsQtextContext) {}
|
|
||||||
|
|
||||||
// ExitObsQtext is called when production obsQtext is exited.
|
|
||||||
func (s *BaseRFC5322ParserListener) ExitObsQtext(ctx *ObsQtextContext) {}
|
|
||||||
|
|
||||||
// EnterObsQP is called when production obsQP is entered.
|
|
||||||
func (s *BaseRFC5322ParserListener) EnterObsQP(ctx *ObsQPContext) {}
|
|
||||||
|
|
||||||
// ExitObsQP is called when production obsQP is exited.
|
|
||||||
func (s *BaseRFC5322ParserListener) ExitObsQP(ctx *ObsQPContext) {}
|
|
||||||
|
|
||||||
// EnterObsFWS is called when production obsFWS is entered.
|
|
||||||
func (s *BaseRFC5322ParserListener) EnterObsFWS(ctx *ObsFWSContext) {}
|
|
||||||
|
|
||||||
// ExitObsFWS is called when production obsFWS is exited.
|
|
||||||
func (s *BaseRFC5322ParserListener) ExitObsFWS(ctx *ObsFWSContext) {}
|
|
||||||
|
|
||||||
// EnterObsZone is called when production obsZone is entered.
|
|
||||||
func (s *BaseRFC5322ParserListener) EnterObsZone(ctx *ObsZoneContext) {}
|
|
||||||
|
|
||||||
// ExitObsZone is called when production obsZone is exited.
|
|
||||||
func (s *BaseRFC5322ParserListener) ExitObsZone(ctx *ObsZoneContext) {}
|
|
||||||
|
|
||||||
// EnterObsAngleAddr is called when production obsAngleAddr is entered.
|
|
||||||
func (s *BaseRFC5322ParserListener) EnterObsAngleAddr(ctx *ObsAngleAddrContext) {}
|
|
||||||
|
|
||||||
// ExitObsAngleAddr is called when production obsAngleAddr is exited.
|
|
||||||
func (s *BaseRFC5322ParserListener) ExitObsAngleAddr(ctx *ObsAngleAddrContext) {}
|
|
||||||
|
|
||||||
// EnterObsRoute is called when production obsRoute is entered.
|
|
||||||
func (s *BaseRFC5322ParserListener) EnterObsRoute(ctx *ObsRouteContext) {}
|
|
||||||
|
|
||||||
// ExitObsRoute is called when production obsRoute is exited.
|
|
||||||
func (s *BaseRFC5322ParserListener) ExitObsRoute(ctx *ObsRouteContext) {}
|
|
||||||
|
|
||||||
// EnterObsDomainList is called when production obsDomainList is entered.
|
|
||||||
func (s *BaseRFC5322ParserListener) EnterObsDomainList(ctx *ObsDomainListContext) {}
|
|
||||||
|
|
||||||
// ExitObsDomainList is called when production obsDomainList is exited.
|
|
||||||
func (s *BaseRFC5322ParserListener) ExitObsDomainList(ctx *ObsDomainListContext) {}
|
|
||||||
|
|
||||||
// EnterObsMboxList is called when production obsMboxList is entered.
|
|
||||||
func (s *BaseRFC5322ParserListener) EnterObsMboxList(ctx *ObsMboxListContext) {}
|
|
||||||
|
|
||||||
// ExitObsMboxList is called when production obsMboxList is exited.
|
|
||||||
func (s *BaseRFC5322ParserListener) ExitObsMboxList(ctx *ObsMboxListContext) {}
|
|
||||||
|
|
||||||
// EnterObsAddrList is called when production obsAddrList is entered.
|
|
||||||
func (s *BaseRFC5322ParserListener) EnterObsAddrList(ctx *ObsAddrListContext) {}
|
|
||||||
|
|
||||||
// ExitObsAddrList is called when production obsAddrList is exited.
|
|
||||||
func (s *BaseRFC5322ParserListener) ExitObsAddrList(ctx *ObsAddrListContext) {}
|
|
||||||
|
|
||||||
// EnterObsGroupList is called when production obsGroupList is entered.
|
|
||||||
func (s *BaseRFC5322ParserListener) EnterObsGroupList(ctx *ObsGroupListContext) {}
|
|
||||||
|
|
||||||
// ExitObsGroupList is called when production obsGroupList is exited.
|
|
||||||
func (s *BaseRFC5322ParserListener) ExitObsGroupList(ctx *ObsGroupListContext) {}
|
|
||||||
|
|
||||||
// EnterObsLocalPart is called when production obsLocalPart is entered.
|
|
||||||
func (s *BaseRFC5322ParserListener) EnterObsLocalPart(ctx *ObsLocalPartContext) {}
|
|
||||||
|
|
||||||
// ExitObsLocalPart is called when production obsLocalPart is exited.
|
|
||||||
func (s *BaseRFC5322ParserListener) ExitObsLocalPart(ctx *ObsLocalPartContext) {}
|
|
||||||
|
|
||||||
// EnterObsDomain is called when production obsDomain is entered.
|
|
||||||
func (s *BaseRFC5322ParserListener) EnterObsDomain(ctx *ObsDomainContext) {}
|
|
||||||
|
|
||||||
// ExitObsDomain is called when production obsDomain is exited.
|
|
||||||
func (s *BaseRFC5322ParserListener) ExitObsDomain(ctx *ObsDomainContext) {}
|
|
||||||
|
|
||||||
// EnterEncodedWord is called when production encodedWord is entered.
|
|
||||||
func (s *BaseRFC5322ParserListener) EnterEncodedWord(ctx *EncodedWordContext) {}
|
|
||||||
|
|
||||||
// ExitEncodedWord is called when production encodedWord is exited.
|
|
||||||
func (s *BaseRFC5322ParserListener) ExitEncodedWord(ctx *EncodedWordContext) {}
|
|
||||||
|
|
||||||
// EnterCharset is called when production charset is entered.
|
|
||||||
func (s *BaseRFC5322ParserListener) EnterCharset(ctx *CharsetContext) {}
|
|
||||||
|
|
||||||
// ExitCharset is called when production charset is exited.
|
|
||||||
func (s *BaseRFC5322ParserListener) ExitCharset(ctx *CharsetContext) {}
|
|
||||||
|
|
||||||
// EnterEncoding is called when production encoding is entered.
|
|
||||||
func (s *BaseRFC5322ParserListener) EnterEncoding(ctx *EncodingContext) {}
|
|
||||||
|
|
||||||
// ExitEncoding is called when production encoding is exited.
|
|
||||||
func (s *BaseRFC5322ParserListener) ExitEncoding(ctx *EncodingContext) {}
|
|
||||||
|
|
||||||
// EnterToken is called when production token is entered.
|
|
||||||
func (s *BaseRFC5322ParserListener) EnterToken(ctx *TokenContext) {}
|
|
||||||
|
|
||||||
// ExitToken is called when production token is exited.
|
|
||||||
func (s *BaseRFC5322ParserListener) ExitToken(ctx *TokenContext) {}
|
|
||||||
|
|
||||||
// EnterTokenChar is called when production tokenChar is entered.
|
|
||||||
func (s *BaseRFC5322ParserListener) EnterTokenChar(ctx *TokenCharContext) {}
|
|
||||||
|
|
||||||
// ExitTokenChar is called when production tokenChar is exited.
|
|
||||||
func (s *BaseRFC5322ParserListener) ExitTokenChar(ctx *TokenCharContext) {}
|
|
||||||
|
|
||||||
// EnterEncodedText is called when production encodedText is entered.
|
|
||||||
func (s *BaseRFC5322ParserListener) EnterEncodedText(ctx *EncodedTextContext) {}
|
|
||||||
|
|
||||||
// ExitEncodedText is called when production encodedText is exited.
|
|
||||||
func (s *BaseRFC5322ParserListener) ExitEncodedText(ctx *EncodedTextContext) {}
|
|
||||||
|
|
||||||
// EnterEncodedChar is called when production encodedChar is entered.
|
|
||||||
func (s *BaseRFC5322ParserListener) EnterEncodedChar(ctx *EncodedCharContext) {}
|
|
||||||
|
|
||||||
// ExitEncodedChar is called when production encodedChar is exited.
|
|
||||||
func (s *BaseRFC5322ParserListener) ExitEncodedChar(ctx *EncodedCharContext) {}
|
|
||||||
|
|
||||||
// EnterCrlf is called when production crlf is entered.
|
|
||||||
func (s *BaseRFC5322ParserListener) EnterCrlf(ctx *CrlfContext) {}
|
|
||||||
|
|
||||||
// ExitCrlf is called when production crlf is exited.
|
|
||||||
func (s *BaseRFC5322ParserListener) ExitCrlf(ctx *CrlfContext) {}
|
|
||||||
|
|
||||||
// EnterWsp is called when production wsp is entered.
|
|
||||||
func (s *BaseRFC5322ParserListener) EnterWsp(ctx *WspContext) {}
|
|
||||||
|
|
||||||
// ExitWsp is called when production wsp is exited.
|
|
||||||
func (s *BaseRFC5322ParserListener) ExitWsp(ctx *WspContext) {}
|
|
||||||
|
|
||||||
// EnterVchar is called when production vchar is entered.
|
|
||||||
func (s *BaseRFC5322ParserListener) EnterVchar(ctx *VcharContext) {}
|
|
||||||
|
|
||||||
// ExitVchar is called when production vchar is exited.
|
|
||||||
func (s *BaseRFC5322ParserListener) ExitVchar(ctx *VcharContext) {}
|
|
||||||
|
|
||||||
// EnterAlpha is called when production alpha is entered.
|
|
||||||
func (s *BaseRFC5322ParserListener) EnterAlpha(ctx *AlphaContext) {}
|
|
||||||
|
|
||||||
// ExitAlpha is called when production alpha is exited.
|
|
||||||
func (s *BaseRFC5322ParserListener) ExitAlpha(ctx *AlphaContext) {}
|
|
||||||
@ -1,423 +0,0 @@
|
|||||||
// Copyright (c) 2020 Proton Technologies AG
|
|
||||||
//
|
|
||||||
// This file is part of ProtonMail Bridge.
|
|
||||||
//
|
|
||||||
// ProtonMail 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.
|
|
||||||
//
|
|
||||||
// ProtonMail 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 ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
// Code generated from RFC5322Parser.g4 by ANTLR 4.8. DO NOT EDIT.
|
|
||||||
|
|
||||||
package parser // RFC5322Parser
|
|
||||||
|
|
||||||
import "github.com/antlr/antlr4/runtime/Go/antlr"
|
|
||||||
|
|
||||||
// RFC5322ParserListener is a complete listener for a parse tree produced by RFC5322Parser.
|
|
||||||
type RFC5322ParserListener interface {
|
|
||||||
antlr.ParseTreeListener
|
|
||||||
|
|
||||||
// EnterQuotedChar is called when entering the quotedChar production.
|
|
||||||
EnterQuotedChar(c *QuotedCharContext)
|
|
||||||
|
|
||||||
// EnterQuotedPair is called when entering the quotedPair production.
|
|
||||||
EnterQuotedPair(c *QuotedPairContext)
|
|
||||||
|
|
||||||
// EnterFws is called when entering the fws production.
|
|
||||||
EnterFws(c *FwsContext)
|
|
||||||
|
|
||||||
// EnterCtext is called when entering the ctext production.
|
|
||||||
EnterCtext(c *CtextContext)
|
|
||||||
|
|
||||||
// EnterCcontent is called when entering the ccontent production.
|
|
||||||
EnterCcontent(c *CcontentContext)
|
|
||||||
|
|
||||||
// EnterComment is called when entering the comment production.
|
|
||||||
EnterComment(c *CommentContext)
|
|
||||||
|
|
||||||
// EnterCfws is called when entering the cfws production.
|
|
||||||
EnterCfws(c *CfwsContext)
|
|
||||||
|
|
||||||
// EnterAtext is called when entering the atext production.
|
|
||||||
EnterAtext(c *AtextContext)
|
|
||||||
|
|
||||||
// EnterAtom is called when entering the atom production.
|
|
||||||
EnterAtom(c *AtomContext)
|
|
||||||
|
|
||||||
// EnterDotAtom is called when entering the dotAtom production.
|
|
||||||
EnterDotAtom(c *DotAtomContext)
|
|
||||||
|
|
||||||
// EnterQtext is called when entering the qtext production.
|
|
||||||
EnterQtext(c *QtextContext)
|
|
||||||
|
|
||||||
// EnterQuotedContent is called when entering the quotedContent production.
|
|
||||||
EnterQuotedContent(c *QuotedContentContext)
|
|
||||||
|
|
||||||
// EnterQuotedValue is called when entering the quotedValue production.
|
|
||||||
EnterQuotedValue(c *QuotedValueContext)
|
|
||||||
|
|
||||||
// EnterQuotedString is called when entering the quotedString production.
|
|
||||||
EnterQuotedString(c *QuotedStringContext)
|
|
||||||
|
|
||||||
// EnterWord is called when entering the word production.
|
|
||||||
EnterWord(c *WordContext)
|
|
||||||
|
|
||||||
// EnterDateTime is called when entering the dateTime production.
|
|
||||||
EnterDateTime(c *DateTimeContext)
|
|
||||||
|
|
||||||
// EnterDayOfweek is called when entering the dayOfweek production.
|
|
||||||
EnterDayOfweek(c *DayOfweekContext)
|
|
||||||
|
|
||||||
// EnterDayName is called when entering the dayName production.
|
|
||||||
EnterDayName(c *DayNameContext)
|
|
||||||
|
|
||||||
// EnterDay is called when entering the day production.
|
|
||||||
EnterDay(c *DayContext)
|
|
||||||
|
|
||||||
// EnterMonth is called when entering the month production.
|
|
||||||
EnterMonth(c *MonthContext)
|
|
||||||
|
|
||||||
// EnterYear is called when entering the year production.
|
|
||||||
EnterYear(c *YearContext)
|
|
||||||
|
|
||||||
// EnterHour is called when entering the hour production.
|
|
||||||
EnterHour(c *HourContext)
|
|
||||||
|
|
||||||
// EnterMinute is called when entering the minute production.
|
|
||||||
EnterMinute(c *MinuteContext)
|
|
||||||
|
|
||||||
// EnterSecond is called when entering the second production.
|
|
||||||
EnterSecond(c *SecondContext)
|
|
||||||
|
|
||||||
// EnterOffset is called when entering the offset production.
|
|
||||||
EnterOffset(c *OffsetContext)
|
|
||||||
|
|
||||||
// EnterZone is called when entering the zone production.
|
|
||||||
EnterZone(c *ZoneContext)
|
|
||||||
|
|
||||||
// EnterAddress is called when entering the address production.
|
|
||||||
EnterAddress(c *AddressContext)
|
|
||||||
|
|
||||||
// EnterMailbox is called when entering the mailbox production.
|
|
||||||
EnterMailbox(c *MailboxContext)
|
|
||||||
|
|
||||||
// EnterNameAddr is called when entering the nameAddr production.
|
|
||||||
EnterNameAddr(c *NameAddrContext)
|
|
||||||
|
|
||||||
// EnterAngleAddr is called when entering the angleAddr production.
|
|
||||||
EnterAngleAddr(c *AngleAddrContext)
|
|
||||||
|
|
||||||
// EnterGroup is called when entering the group production.
|
|
||||||
EnterGroup(c *GroupContext)
|
|
||||||
|
|
||||||
// EnterDisplayName is called when entering the displayName production.
|
|
||||||
EnterDisplayName(c *DisplayNameContext)
|
|
||||||
|
|
||||||
// EnterMailboxList is called when entering the mailboxList production.
|
|
||||||
EnterMailboxList(c *MailboxListContext)
|
|
||||||
|
|
||||||
// EnterAddressList is called when entering the addressList production.
|
|
||||||
EnterAddressList(c *AddressListContext)
|
|
||||||
|
|
||||||
// EnterGroupList is called when entering the groupList production.
|
|
||||||
EnterGroupList(c *GroupListContext)
|
|
||||||
|
|
||||||
// EnterAddrSpec is called when entering the addrSpec production.
|
|
||||||
EnterAddrSpec(c *AddrSpecContext)
|
|
||||||
|
|
||||||
// EnterLocalPart is called when entering the localPart production.
|
|
||||||
EnterLocalPart(c *LocalPartContext)
|
|
||||||
|
|
||||||
// EnterPort is called when entering the port production.
|
|
||||||
EnterPort(c *PortContext)
|
|
||||||
|
|
||||||
// EnterDomain is called when entering the domain production.
|
|
||||||
EnterDomain(c *DomainContext)
|
|
||||||
|
|
||||||
// EnterDomainLiteral is called when entering the domainLiteral production.
|
|
||||||
EnterDomainLiteral(c *DomainLiteralContext)
|
|
||||||
|
|
||||||
// EnterDtext is called when entering the dtext production.
|
|
||||||
EnterDtext(c *DtextContext)
|
|
||||||
|
|
||||||
// EnterObsNoWSCTL is called when entering the obsNoWSCTL production.
|
|
||||||
EnterObsNoWSCTL(c *ObsNoWSCTLContext)
|
|
||||||
|
|
||||||
// EnterObsCtext is called when entering the obsCtext production.
|
|
||||||
EnterObsCtext(c *ObsCtextContext)
|
|
||||||
|
|
||||||
// EnterObsQtext is called when entering the obsQtext production.
|
|
||||||
EnterObsQtext(c *ObsQtextContext)
|
|
||||||
|
|
||||||
// EnterObsQP is called when entering the obsQP production.
|
|
||||||
EnterObsQP(c *ObsQPContext)
|
|
||||||
|
|
||||||
// EnterObsFWS is called when entering the obsFWS production.
|
|
||||||
EnterObsFWS(c *ObsFWSContext)
|
|
||||||
|
|
||||||
// EnterObsZone is called when entering the obsZone production.
|
|
||||||
EnterObsZone(c *ObsZoneContext)
|
|
||||||
|
|
||||||
// EnterObsAngleAddr is called when entering the obsAngleAddr production.
|
|
||||||
EnterObsAngleAddr(c *ObsAngleAddrContext)
|
|
||||||
|
|
||||||
// EnterObsRoute is called when entering the obsRoute production.
|
|
||||||
EnterObsRoute(c *ObsRouteContext)
|
|
||||||
|
|
||||||
// EnterObsDomainList is called when entering the obsDomainList production.
|
|
||||||
EnterObsDomainList(c *ObsDomainListContext)
|
|
||||||
|
|
||||||
// EnterObsMboxList is called when entering the obsMboxList production.
|
|
||||||
EnterObsMboxList(c *ObsMboxListContext)
|
|
||||||
|
|
||||||
// EnterObsAddrList is called when entering the obsAddrList production.
|
|
||||||
EnterObsAddrList(c *ObsAddrListContext)
|
|
||||||
|
|
||||||
// EnterObsGroupList is called when entering the obsGroupList production.
|
|
||||||
EnterObsGroupList(c *ObsGroupListContext)
|
|
||||||
|
|
||||||
// EnterObsLocalPart is called when entering the obsLocalPart production.
|
|
||||||
EnterObsLocalPart(c *ObsLocalPartContext)
|
|
||||||
|
|
||||||
// EnterObsDomain is called when entering the obsDomain production.
|
|
||||||
EnterObsDomain(c *ObsDomainContext)
|
|
||||||
|
|
||||||
// EnterEncodedWord is called when entering the encodedWord production.
|
|
||||||
EnterEncodedWord(c *EncodedWordContext)
|
|
||||||
|
|
||||||
// EnterCharset is called when entering the charset production.
|
|
||||||
EnterCharset(c *CharsetContext)
|
|
||||||
|
|
||||||
// EnterEncoding is called when entering the encoding production.
|
|
||||||
EnterEncoding(c *EncodingContext)
|
|
||||||
|
|
||||||
// EnterToken is called when entering the token production.
|
|
||||||
EnterToken(c *TokenContext)
|
|
||||||
|
|
||||||
// EnterTokenChar is called when entering the tokenChar production.
|
|
||||||
EnterTokenChar(c *TokenCharContext)
|
|
||||||
|
|
||||||
// EnterEncodedText is called when entering the encodedText production.
|
|
||||||
EnterEncodedText(c *EncodedTextContext)
|
|
||||||
|
|
||||||
// EnterEncodedChar is called when entering the encodedChar production.
|
|
||||||
EnterEncodedChar(c *EncodedCharContext)
|
|
||||||
|
|
||||||
// EnterCrlf is called when entering the crlf production.
|
|
||||||
EnterCrlf(c *CrlfContext)
|
|
||||||
|
|
||||||
// EnterWsp is called when entering the wsp production.
|
|
||||||
EnterWsp(c *WspContext)
|
|
||||||
|
|
||||||
// EnterVchar is called when entering the vchar production.
|
|
||||||
EnterVchar(c *VcharContext)
|
|
||||||
|
|
||||||
// EnterAlpha is called when entering the alpha production.
|
|
||||||
EnterAlpha(c *AlphaContext)
|
|
||||||
|
|
||||||
// ExitQuotedChar is called when exiting the quotedChar production.
|
|
||||||
ExitQuotedChar(c *QuotedCharContext)
|
|
||||||
|
|
||||||
// ExitQuotedPair is called when exiting the quotedPair production.
|
|
||||||
ExitQuotedPair(c *QuotedPairContext)
|
|
||||||
|
|
||||||
// ExitFws is called when exiting the fws production.
|
|
||||||
ExitFws(c *FwsContext)
|
|
||||||
|
|
||||||
// ExitCtext is called when exiting the ctext production.
|
|
||||||
ExitCtext(c *CtextContext)
|
|
||||||
|
|
||||||
// ExitCcontent is called when exiting the ccontent production.
|
|
||||||
ExitCcontent(c *CcontentContext)
|
|
||||||
|
|
||||||
// ExitComment is called when exiting the comment production.
|
|
||||||
ExitComment(c *CommentContext)
|
|
||||||
|
|
||||||
// ExitCfws is called when exiting the cfws production.
|
|
||||||
ExitCfws(c *CfwsContext)
|
|
||||||
|
|
||||||
// ExitAtext is called when exiting the atext production.
|
|
||||||
ExitAtext(c *AtextContext)
|
|
||||||
|
|
||||||
// ExitAtom is called when exiting the atom production.
|
|
||||||
ExitAtom(c *AtomContext)
|
|
||||||
|
|
||||||
// ExitDotAtom is called when exiting the dotAtom production.
|
|
||||||
ExitDotAtom(c *DotAtomContext)
|
|
||||||
|
|
||||||
// ExitQtext is called when exiting the qtext production.
|
|
||||||
ExitQtext(c *QtextContext)
|
|
||||||
|
|
||||||
// ExitQuotedContent is called when exiting the quotedContent production.
|
|
||||||
ExitQuotedContent(c *QuotedContentContext)
|
|
||||||
|
|
||||||
// ExitQuotedValue is called when exiting the quotedValue production.
|
|
||||||
ExitQuotedValue(c *QuotedValueContext)
|
|
||||||
|
|
||||||
// ExitQuotedString is called when exiting the quotedString production.
|
|
||||||
ExitQuotedString(c *QuotedStringContext)
|
|
||||||
|
|
||||||
// ExitWord is called when exiting the word production.
|
|
||||||
ExitWord(c *WordContext)
|
|
||||||
|
|
||||||
// ExitDateTime is called when exiting the dateTime production.
|
|
||||||
ExitDateTime(c *DateTimeContext)
|
|
||||||
|
|
||||||
// ExitDayOfweek is called when exiting the dayOfweek production.
|
|
||||||
ExitDayOfweek(c *DayOfweekContext)
|
|
||||||
|
|
||||||
// ExitDayName is called when exiting the dayName production.
|
|
||||||
ExitDayName(c *DayNameContext)
|
|
||||||
|
|
||||||
// ExitDay is called when exiting the day production.
|
|
||||||
ExitDay(c *DayContext)
|
|
||||||
|
|
||||||
// ExitMonth is called when exiting the month production.
|
|
||||||
ExitMonth(c *MonthContext)
|
|
||||||
|
|
||||||
// ExitYear is called when exiting the year production.
|
|
||||||
ExitYear(c *YearContext)
|
|
||||||
|
|
||||||
// ExitHour is called when exiting the hour production.
|
|
||||||
ExitHour(c *HourContext)
|
|
||||||
|
|
||||||
// ExitMinute is called when exiting the minute production.
|
|
||||||
ExitMinute(c *MinuteContext)
|
|
||||||
|
|
||||||
// ExitSecond is called when exiting the second production.
|
|
||||||
ExitSecond(c *SecondContext)
|
|
||||||
|
|
||||||
// ExitOffset is called when exiting the offset production.
|
|
||||||
ExitOffset(c *OffsetContext)
|
|
||||||
|
|
||||||
// ExitZone is called when exiting the zone production.
|
|
||||||
ExitZone(c *ZoneContext)
|
|
||||||
|
|
||||||
// ExitAddress is called when exiting the address production.
|
|
||||||
ExitAddress(c *AddressContext)
|
|
||||||
|
|
||||||
// ExitMailbox is called when exiting the mailbox production.
|
|
||||||
ExitMailbox(c *MailboxContext)
|
|
||||||
|
|
||||||
// ExitNameAddr is called when exiting the nameAddr production.
|
|
||||||
ExitNameAddr(c *NameAddrContext)
|
|
||||||
|
|
||||||
// ExitAngleAddr is called when exiting the angleAddr production.
|
|
||||||
ExitAngleAddr(c *AngleAddrContext)
|
|
||||||
|
|
||||||
// ExitGroup is called when exiting the group production.
|
|
||||||
ExitGroup(c *GroupContext)
|
|
||||||
|
|
||||||
// ExitDisplayName is called when exiting the displayName production.
|
|
||||||
ExitDisplayName(c *DisplayNameContext)
|
|
||||||
|
|
||||||
// ExitMailboxList is called when exiting the mailboxList production.
|
|
||||||
ExitMailboxList(c *MailboxListContext)
|
|
||||||
|
|
||||||
// ExitAddressList is called when exiting the addressList production.
|
|
||||||
ExitAddressList(c *AddressListContext)
|
|
||||||
|
|
||||||
// ExitGroupList is called when exiting the groupList production.
|
|
||||||
ExitGroupList(c *GroupListContext)
|
|
||||||
|
|
||||||
// ExitAddrSpec is called when exiting the addrSpec production.
|
|
||||||
ExitAddrSpec(c *AddrSpecContext)
|
|
||||||
|
|
||||||
// ExitLocalPart is called when exiting the localPart production.
|
|
||||||
ExitLocalPart(c *LocalPartContext)
|
|
||||||
|
|
||||||
// ExitPort is called when exiting the port production.
|
|
||||||
ExitPort(c *PortContext)
|
|
||||||
|
|
||||||
// ExitDomain is called when exiting the domain production.
|
|
||||||
ExitDomain(c *DomainContext)
|
|
||||||
|
|
||||||
// ExitDomainLiteral is called when exiting the domainLiteral production.
|
|
||||||
ExitDomainLiteral(c *DomainLiteralContext)
|
|
||||||
|
|
||||||
// ExitDtext is called when exiting the dtext production.
|
|
||||||
ExitDtext(c *DtextContext)
|
|
||||||
|
|
||||||
// ExitObsNoWSCTL is called when exiting the obsNoWSCTL production.
|
|
||||||
ExitObsNoWSCTL(c *ObsNoWSCTLContext)
|
|
||||||
|
|
||||||
// ExitObsCtext is called when exiting the obsCtext production.
|
|
||||||
ExitObsCtext(c *ObsCtextContext)
|
|
||||||
|
|
||||||
// ExitObsQtext is called when exiting the obsQtext production.
|
|
||||||
ExitObsQtext(c *ObsQtextContext)
|
|
||||||
|
|
||||||
// ExitObsQP is called when exiting the obsQP production.
|
|
||||||
ExitObsQP(c *ObsQPContext)
|
|
||||||
|
|
||||||
// ExitObsFWS is called when exiting the obsFWS production.
|
|
||||||
ExitObsFWS(c *ObsFWSContext)
|
|
||||||
|
|
||||||
// ExitObsZone is called when exiting the obsZone production.
|
|
||||||
ExitObsZone(c *ObsZoneContext)
|
|
||||||
|
|
||||||
// ExitObsAngleAddr is called when exiting the obsAngleAddr production.
|
|
||||||
ExitObsAngleAddr(c *ObsAngleAddrContext)
|
|
||||||
|
|
||||||
// ExitObsRoute is called when exiting the obsRoute production.
|
|
||||||
ExitObsRoute(c *ObsRouteContext)
|
|
||||||
|
|
||||||
// ExitObsDomainList is called when exiting the obsDomainList production.
|
|
||||||
ExitObsDomainList(c *ObsDomainListContext)
|
|
||||||
|
|
||||||
// ExitObsMboxList is called when exiting the obsMboxList production.
|
|
||||||
ExitObsMboxList(c *ObsMboxListContext)
|
|
||||||
|
|
||||||
// ExitObsAddrList is called when exiting the obsAddrList production.
|
|
||||||
ExitObsAddrList(c *ObsAddrListContext)
|
|
||||||
|
|
||||||
// ExitObsGroupList is called when exiting the obsGroupList production.
|
|
||||||
ExitObsGroupList(c *ObsGroupListContext)
|
|
||||||
|
|
||||||
// ExitObsLocalPart is called when exiting the obsLocalPart production.
|
|
||||||
ExitObsLocalPart(c *ObsLocalPartContext)
|
|
||||||
|
|
||||||
// ExitObsDomain is called when exiting the obsDomain production.
|
|
||||||
ExitObsDomain(c *ObsDomainContext)
|
|
||||||
|
|
||||||
// ExitEncodedWord is called when exiting the encodedWord production.
|
|
||||||
ExitEncodedWord(c *EncodedWordContext)
|
|
||||||
|
|
||||||
// ExitCharset is called when exiting the charset production.
|
|
||||||
ExitCharset(c *CharsetContext)
|
|
||||||
|
|
||||||
// ExitEncoding is called when exiting the encoding production.
|
|
||||||
ExitEncoding(c *EncodingContext)
|
|
||||||
|
|
||||||
// ExitToken is called when exiting the token production.
|
|
||||||
ExitToken(c *TokenContext)
|
|
||||||
|
|
||||||
// ExitTokenChar is called when exiting the tokenChar production.
|
|
||||||
ExitTokenChar(c *TokenCharContext)
|
|
||||||
|
|
||||||
// ExitEncodedText is called when exiting the encodedText production.
|
|
||||||
ExitEncodedText(c *EncodedTextContext)
|
|
||||||
|
|
||||||
// ExitEncodedChar is called when exiting the encodedChar production.
|
|
||||||
ExitEncodedChar(c *EncodedCharContext)
|
|
||||||
|
|
||||||
// ExitCrlf is called when exiting the crlf production.
|
|
||||||
ExitCrlf(c *CrlfContext)
|
|
||||||
|
|
||||||
// ExitWsp is called when exiting the wsp production.
|
|
||||||
ExitWsp(c *WspContext)
|
|
||||||
|
|
||||||
// ExitVchar is called when exiting the vchar production.
|
|
||||||
ExitVchar(c *VcharContext)
|
|
||||||
|
|
||||||
// ExitAlpha is called when exiting the alpha production.
|
|
||||||
ExitAlpha(c *AlphaContext)
|
|
||||||
}
|
|
||||||
@ -1,49 +0,0 @@
|
|||||||
// Copyright (c) 2020 Proton Technologies AG
|
|
||||||
//
|
|
||||||
// This file is part of ProtonMail Bridge.
|
|
||||||
//
|
|
||||||
// ProtonMail 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.
|
|
||||||
//
|
|
||||||
// ProtonMail 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 ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
package rfc5322
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/ProtonMail/proton-bridge/pkg/message/rfc5322/parser"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
|
||||||
|
|
||||||
type port struct {
|
|
||||||
value string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) EnterPort(ctx *parser.PortContext) {
|
|
||||||
logrus.WithField("text", ctx.GetText()).Trace("Entering port")
|
|
||||||
|
|
||||||
w.enter(&port{
|
|
||||||
value: ctx.GetText(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) ExitPort(ctx *parser.PortContext) {
|
|
||||||
logrus.WithField("text", ctx.GetText()).Trace("Exiting port")
|
|
||||||
|
|
||||||
type withPort interface {
|
|
||||||
withPort(*port)
|
|
||||||
}
|
|
||||||
|
|
||||||
res := w.exit().(*port)
|
|
||||||
|
|
||||||
if parent, ok := w.parent().(withPort); ok {
|
|
||||||
parent.withPort(res)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,49 +0,0 @@
|
|||||||
// Copyright (c) 2020 Proton Technologies AG
|
|
||||||
//
|
|
||||||
// This file is part of ProtonMail Bridge.
|
|
||||||
//
|
|
||||||
// ProtonMail 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.
|
|
||||||
//
|
|
||||||
// ProtonMail 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 ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
package rfc5322
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/ProtonMail/proton-bridge/pkg/message/rfc5322/parser"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
|
||||||
|
|
||||||
type qtext struct {
|
|
||||||
value string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) EnterQtext(ctx *parser.QtextContext) {
|
|
||||||
logrus.WithField("text", ctx.GetText()).Trace("Entering qtext")
|
|
||||||
|
|
||||||
w.enter(&qtext{
|
|
||||||
value: ctx.GetText(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) ExitQtext(ctx *parser.QtextContext) {
|
|
||||||
logrus.WithField("text", ctx.GetText()).Trace("Exiting qtext")
|
|
||||||
|
|
||||||
type withQtext interface {
|
|
||||||
withQtext(*qtext)
|
|
||||||
}
|
|
||||||
|
|
||||||
res := w.exit().(*qtext)
|
|
||||||
|
|
||||||
if parent, ok := w.parent().(withQtext); ok {
|
|
||||||
parent.withQtext(res)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,49 +0,0 @@
|
|||||||
// Copyright (c) 2020 Proton Technologies AG
|
|
||||||
//
|
|
||||||
// This file is part of ProtonMail Bridge.
|
|
||||||
//
|
|
||||||
// ProtonMail 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.
|
|
||||||
//
|
|
||||||
// ProtonMail 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 ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
package rfc5322
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/ProtonMail/proton-bridge/pkg/message/rfc5322/parser"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
|
||||||
|
|
||||||
type quotedChar struct {
|
|
||||||
value string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) EnterQuotedChar(ctx *parser.QuotedCharContext) {
|
|
||||||
logrus.WithField("text", ctx.GetText()).Trace("Entering quotedChar")
|
|
||||||
|
|
||||||
w.enter("edChar{
|
|
||||||
value: ctx.GetText(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) ExitQuotedChar(ctx *parser.QuotedCharContext) {
|
|
||||||
logrus.WithField("text", ctx.GetText()).Trace("Exiting quotedChar")
|
|
||||||
|
|
||||||
type withQuotedChar interface {
|
|
||||||
withQuotedChar(*quotedChar)
|
|
||||||
}
|
|
||||||
|
|
||||||
res := w.exit().(*quotedChar)
|
|
||||||
|
|
||||||
if parent, ok := w.parent().(withQuotedChar); ok {
|
|
||||||
parent.withQuotedChar(res)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,54 +0,0 @@
|
|||||||
// Copyright (c) 2020 Proton Technologies AG
|
|
||||||
//
|
|
||||||
// This file is part of ProtonMail Bridge.
|
|
||||||
//
|
|
||||||
// ProtonMail 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.
|
|
||||||
//
|
|
||||||
// ProtonMail 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 ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
package rfc5322
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/ProtonMail/proton-bridge/pkg/message/rfc5322/parser"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
|
||||||
|
|
||||||
type quotedContent struct {
|
|
||||||
value string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *quotedContent) withQtext(qtext *qtext) {
|
|
||||||
c.value = qtext.value
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *quotedContent) withQuotedPair(quotedPair *quotedPair) {
|
|
||||||
c.value = quotedPair.value
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) EnterQuotedContent(ctx *parser.QuotedContentContext) {
|
|
||||||
logrus.WithField("text", ctx.GetText()).Trace("Entering quotedContent")
|
|
||||||
w.enter("edContent{})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) ExitQuotedContent(ctx *parser.QuotedContentContext) {
|
|
||||||
logrus.WithField("text", ctx.GetText()).Trace("Exiting quotedContent")
|
|
||||||
|
|
||||||
type withQuotedContent interface {
|
|
||||||
withQuotedContent(*quotedContent)
|
|
||||||
}
|
|
||||||
|
|
||||||
res := w.exit().(*quotedContent)
|
|
||||||
|
|
||||||
if parent, ok := w.parent().(withQuotedContent); ok {
|
|
||||||
parent.withQuotedContent(res)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,50 +0,0 @@
|
|||||||
// Copyright (c) 2020 Proton Technologies AG
|
|
||||||
//
|
|
||||||
// This file is part of ProtonMail Bridge.
|
|
||||||
//
|
|
||||||
// ProtonMail 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.
|
|
||||||
//
|
|
||||||
// ProtonMail 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 ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
package rfc5322
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/ProtonMail/proton-bridge/pkg/message/rfc5322/parser"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
|
||||||
|
|
||||||
type quotedPair struct {
|
|
||||||
value string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *quotedPair) withQuotedChar(quotedChar *quotedChar) {
|
|
||||||
p.value = quotedChar.value
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) EnterQuotedPair(ctx *parser.QuotedPairContext) {
|
|
||||||
logrus.WithField("text", ctx.GetText()).Trace("Entering quotedPair")
|
|
||||||
w.enter("edPair{})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) ExitQuotedPair(ctx *parser.QuotedPairContext) {
|
|
||||||
logrus.WithField("text", ctx.GetText()).Trace("Exiting quotedPair")
|
|
||||||
|
|
||||||
type withQuotedPair interface {
|
|
||||||
withQuotedPair(*quotedPair)
|
|
||||||
}
|
|
||||||
|
|
||||||
res := w.exit().(*quotedPair)
|
|
||||||
|
|
||||||
if parent, ok := w.parent().(withQuotedPair); ok {
|
|
||||||
parent.withQuotedPair(res)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,50 +0,0 @@
|
|||||||
// Copyright (c) 2020 Proton Technologies AG
|
|
||||||
//
|
|
||||||
// This file is part of ProtonMail Bridge.
|
|
||||||
//
|
|
||||||
// ProtonMail 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.
|
|
||||||
//
|
|
||||||
// ProtonMail 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 ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
package rfc5322
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/ProtonMail/proton-bridge/pkg/message/rfc5322/parser"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
|
||||||
|
|
||||||
type quotedString struct {
|
|
||||||
value string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *quotedString) withQuotedValue(quotedValue *quotedValue) {
|
|
||||||
s.value = quotedValue.value
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) EnterQuotedString(ctx *parser.QuotedStringContext) {
|
|
||||||
logrus.WithField("text", ctx.GetText()).Trace("Entering quotedString")
|
|
||||||
w.enter("edString{})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) ExitQuotedString(ctx *parser.QuotedStringContext) {
|
|
||||||
logrus.WithField("text", ctx.GetText()).Trace("Exiting quotedString")
|
|
||||||
|
|
||||||
type withQuotedString interface {
|
|
||||||
withQuotedString(*quotedString)
|
|
||||||
}
|
|
||||||
|
|
||||||
res := w.exit().(*quotedString)
|
|
||||||
|
|
||||||
if parent, ok := w.parent().(withQuotedString); ok {
|
|
||||||
parent.withQuotedString(res)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,54 +0,0 @@
|
|||||||
// Copyright (c) 2020 Proton Technologies AG
|
|
||||||
//
|
|
||||||
// This file is part of ProtonMail Bridge.
|
|
||||||
//
|
|
||||||
// ProtonMail 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.
|
|
||||||
//
|
|
||||||
// ProtonMail 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 ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
package rfc5322
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/ProtonMail/proton-bridge/pkg/message/rfc5322/parser"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
|
||||||
|
|
||||||
type quotedValue struct {
|
|
||||||
value string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *quotedValue) withFws(fws *fws) {
|
|
||||||
v.value += fws.value
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *quotedValue) withQuotedContent(quotedContent *quotedContent) {
|
|
||||||
v.value += quotedContent.value
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) EnterQuotedValue(ctx *parser.QuotedValueContext) {
|
|
||||||
logrus.WithField("text", ctx.GetText()).Trace("Entering quotedValue")
|
|
||||||
w.enter("edValue{})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) ExitQuotedValue(ctx *parser.QuotedValueContext) {
|
|
||||||
logrus.WithField("text", ctx.GetText()).Trace("Exiting quotedValue")
|
|
||||||
|
|
||||||
type withQuotedValue interface {
|
|
||||||
withQuotedValue(*quotedValue)
|
|
||||||
}
|
|
||||||
|
|
||||||
res := w.exit().(*quotedValue)
|
|
||||||
|
|
||||||
if parent, ok := w.parent().(withQuotedValue); ok {
|
|
||||||
parent.withQuotedValue(res)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,62 +0,0 @@
|
|||||||
// Copyright (c) 2020 Proton Technologies AG
|
|
||||||
//
|
|
||||||
// This file is part of ProtonMail Bridge.
|
|
||||||
//
|
|
||||||
// ProtonMail 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.
|
|
||||||
//
|
|
||||||
// ProtonMail 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 ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
package rfc5322
|
|
||||||
|
|
||||||
import (
|
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"github.com/ProtonMail/proton-bridge/pkg/message/rfc5322/parser"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
|
||||||
|
|
||||||
type second struct {
|
|
||||||
value int
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) EnterSecond(ctx *parser.SecondContext) {
|
|
||||||
logrus.WithField("text", ctx.GetText()).Trace("Entering second")
|
|
||||||
|
|
||||||
var text string
|
|
||||||
|
|
||||||
for _, digit := range ctx.AllDigit() {
|
|
||||||
text += digit.GetText()
|
|
||||||
}
|
|
||||||
|
|
||||||
val, err := strconv.Atoi(text)
|
|
||||||
if err != nil {
|
|
||||||
w.err = err
|
|
||||||
}
|
|
||||||
|
|
||||||
w.enter(&second{
|
|
||||||
value: val,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) ExitSecond(ctx *parser.SecondContext) {
|
|
||||||
logrus.WithField("text", ctx.GetText()).Trace("Exiting second")
|
|
||||||
|
|
||||||
type withSecond interface {
|
|
||||||
withSecond(*second)
|
|
||||||
}
|
|
||||||
|
|
||||||
res := w.exit().(*second)
|
|
||||||
|
|
||||||
if parent, ok := w.parent().(withSecond); ok {
|
|
||||||
parent.withSecond(res)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
@ -1,62 +0,0 @@
|
|||||||
// Copyright (c) 2020 Proton Technologies AG
|
|
||||||
//
|
|
||||||
// This file is part of ProtonMail Bridge.
|
|
||||||
//
|
|
||||||
// ProtonMail 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.
|
|
||||||
//
|
|
||||||
// ProtonMail 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 ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
package rfc5322
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/ProtonMail/proton-bridge/pkg/message/rfc5322/parser"
|
|
||||||
"github.com/antlr/antlr4/runtime/Go/antlr"
|
|
||||||
)
|
|
||||||
|
|
||||||
// walker implements parser.BaseRFC5322ParserListener, defining what to do at
|
|
||||||
// each node while traversing the syntax tree.
|
|
||||||
// It also implements antlr.DefaultErrorListener, allowing us to react to
|
|
||||||
// errors encountered while trying to determine the syntax tree of the input.
|
|
||||||
type walker struct {
|
|
||||||
parser.BaseRFC5322ParserListener
|
|
||||||
antlr.DefaultErrorListener
|
|
||||||
|
|
||||||
// nodes acts as a stack; when entering a node, it is pushed here, and when
|
|
||||||
// exiting a node, it is popped from here.
|
|
||||||
nodes []interface{}
|
|
||||||
|
|
||||||
// res holds the result of walking the parse tree.
|
|
||||||
res interface{}
|
|
||||||
|
|
||||||
// err holds the error encountered during parsing, if any.
|
|
||||||
err error
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) enter(b interface{}) {
|
|
||||||
w.nodes = append(w.nodes, b)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) exit() interface{} {
|
|
||||||
b := w.nodes[len(w.nodes)-1]
|
|
||||||
w.nodes = w.nodes[:len(w.nodes)-1]
|
|
||||||
return b
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) parent() (b interface{}) {
|
|
||||||
return w.nodes[len(w.nodes)-1]
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) SyntaxError(_ antlr.Recognizer, _ interface{}, _, _ int, msg string, _ antlr.RecognitionException) {
|
|
||||||
w.err = fmt.Errorf("error parsing rfc5322 input: %v", msg)
|
|
||||||
}
|
|
||||||
@ -1,61 +0,0 @@
|
|||||||
// Copyright (c) 2020 Proton Technologies AG
|
|
||||||
//
|
|
||||||
// This file is part of ProtonMail Bridge.
|
|
||||||
//
|
|
||||||
// ProtonMail 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.
|
|
||||||
//
|
|
||||||
// ProtonMail 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 ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
package rfc5322
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/ProtonMail/proton-bridge/pkg/message/rfc5322/parser"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
|
||||||
|
|
||||||
type word struct {
|
|
||||||
value string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *word) withAtom(atom *atom) {
|
|
||||||
w.value = atom.value
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *word) withQuotedString(quotedString *quotedString) {
|
|
||||||
w.value = quotedString.value
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *word) withEncodedWord(encodedWord *encodedWord) {
|
|
||||||
w.value = encodedWord.value
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) EnterWord(ctx *parser.WordContext) {
|
|
||||||
logrus.WithField("text", ctx.GetText()).Trace("Entering word")
|
|
||||||
|
|
||||||
w.enter(&word{
|
|
||||||
value: ctx.GetText(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) ExitWord(ctx *parser.WordContext) {
|
|
||||||
logrus.WithField("text", ctx.GetText()).Trace("Exiting word")
|
|
||||||
|
|
||||||
type withWord interface {
|
|
||||||
withWord(*word)
|
|
||||||
}
|
|
||||||
|
|
||||||
res := w.exit().(*word)
|
|
||||||
|
|
||||||
if parent, ok := w.parent().(withWord); ok {
|
|
||||||
parent.withWord(res)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,72 +0,0 @@
|
|||||||
// Copyright (c) 2020 Proton Technologies AG
|
|
||||||
//
|
|
||||||
// This file is part of ProtonMail Bridge.
|
|
||||||
//
|
|
||||||
// ProtonMail 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.
|
|
||||||
//
|
|
||||||
// ProtonMail 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 ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
package rfc5322
|
|
||||||
|
|
||||||
import (
|
|
||||||
"strconv"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/ProtonMail/proton-bridge/pkg/message/rfc5322/parser"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
|
||||||
|
|
||||||
type year struct {
|
|
||||||
value int
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) EnterYear(ctx *parser.YearContext) {
|
|
||||||
logrus.WithField("text", ctx.GetText()).Trace("Entering year")
|
|
||||||
|
|
||||||
var text string
|
|
||||||
|
|
||||||
for _, digit := range ctx.AllDigit() {
|
|
||||||
text += digit.GetText()
|
|
||||||
}
|
|
||||||
|
|
||||||
val, err := strconv.Atoi(text)
|
|
||||||
if err != nil {
|
|
||||||
w.err = err
|
|
||||||
}
|
|
||||||
|
|
||||||
// NOTE: 2-digit years are obsolete but let's just have some simple handling anyway.
|
|
||||||
if len(text) == 2 {
|
|
||||||
if val > time.Now().Year()%100 {
|
|
||||||
val += 1900
|
|
||||||
} else {
|
|
||||||
val += 2000
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
w.enter(&year{
|
|
||||||
value: val,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) ExitYear(ctx *parser.YearContext) {
|
|
||||||
logrus.WithField("text", ctx.GetText()).Trace("Exiting year")
|
|
||||||
|
|
||||||
type withYear interface {
|
|
||||||
withYear(*year)
|
|
||||||
}
|
|
||||||
|
|
||||||
res := w.exit().(*year)
|
|
||||||
|
|
||||||
if parent, ok := w.parent().(withYear); ok {
|
|
||||||
parent.withYear(res)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,59 +0,0 @@
|
|||||||
// Copyright (c) 2020 Proton Technologies AG
|
|
||||||
//
|
|
||||||
// This file is part of ProtonMail Bridge.
|
|
||||||
//
|
|
||||||
// ProtonMail 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.
|
|
||||||
//
|
|
||||||
// ProtonMail 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 ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
package rfc5322
|
|
||||||
|
|
||||||
import (
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/ProtonMail/proton-bridge/pkg/message/rfc5322/parser"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
|
||||||
|
|
||||||
type zone struct {
|
|
||||||
location *time.Location
|
|
||||||
}
|
|
||||||
|
|
||||||
func (z *zone) withOffset(offset *offset) {
|
|
||||||
z.location = time.FixedZone(offset.rep, offset.value)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (z *zone) withObsZone(obsZone *obsZone) {
|
|
||||||
z.location = obsZone.location
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) EnterZone(ctx *parser.ZoneContext) {
|
|
||||||
logrus.WithField("text", ctx.GetText()).Trace("Entering zone")
|
|
||||||
|
|
||||||
w.enter(&zone{
|
|
||||||
location: time.UTC,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *walker) ExitZone(ctx *parser.ZoneContext) {
|
|
||||||
logrus.WithField("text", ctx.GetText()).Trace("Exiting zone")
|
|
||||||
|
|
||||||
type withZone interface {
|
|
||||||
withZone(*zone)
|
|
||||||
}
|
|
||||||
|
|
||||||
res := w.exit().(*zone)
|
|
||||||
|
|
||||||
if parent, ok := w.parent().(withZone); ok {
|
|
||||||
parent.withZone(res)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -32,17 +32,19 @@ import (
|
|||||||
"golang.org/x/text/encoding/htmlindex"
|
"golang.org/x/text/encoding/htmlindex"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func CharsetReader(charset string, input io.Reader) (io.Reader, error) {
|
||||||
|
dec, err := SelectDecoder(charset)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if dec == nil { // utf-8
|
||||||
|
return input, nil
|
||||||
|
}
|
||||||
|
return dec.Reader(input), nil
|
||||||
|
}
|
||||||
|
|
||||||
var WordDec = &mime.WordDecoder{
|
var WordDec = &mime.WordDecoder{
|
||||||
CharsetReader: func(charset string, input io.Reader) (io.Reader, error) {
|
CharsetReader: CharsetReader,
|
||||||
dec, err := SelectDecoder(charset)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if dec == nil { // utf-8
|
|
||||||
return input, nil
|
|
||||||
}
|
|
||||||
return dec.Reader(input), nil
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Expects trimmed lowercase.
|
// Expects trimmed lowercase.
|
||||||
|
|||||||
@ -15,7 +15,7 @@
|
|||||||
// 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 ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
// along with ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
// +build pmapi_env
|
// +build pmapi_qa
|
||||||
|
|
||||||
package pmapi
|
package pmapi
|
||||||
|
|
||||||
|
|||||||
@ -5,12 +5,11 @@
|
|||||||
package mocks
|
package mocks
|
||||||
|
|
||||||
import (
|
import (
|
||||||
io "io"
|
|
||||||
reflect "reflect"
|
|
||||||
|
|
||||||
crypto "github.com/ProtonMail/gopenpgp/v2/crypto"
|
crypto "github.com/ProtonMail/gopenpgp/v2/crypto"
|
||||||
pmapi "github.com/ProtonMail/proton-bridge/pkg/pmapi"
|
pmapi "github.com/ProtonMail/proton-bridge/pkg/pmapi"
|
||||||
gomock "github.com/golang/mock/gomock"
|
gomock "github.com/golang/mock/gomock"
|
||||||
|
io "io"
|
||||||
|
reflect "reflect"
|
||||||
)
|
)
|
||||||
|
|
||||||
// MockClient is a mock of Client interface
|
// MockClient is a mock of Client interface
|
||||||
|
|||||||
@ -1,3 +0,0 @@
|
|||||||
• Linux font issues - Fedora specific
|
|
||||||
• App response to the user pausing and canceling import or export
|
|
||||||
• Handling errors during update
|
|
||||||
|
|||||||
@ -1,5 +1,3 @@
|
|||||||
• Improvements to the import from large mbox files with multiple labels
|
• Further improvements to address and date parsing
|
||||||
• Not allow to run multiple instances of the app or transfers at the same time
|
• Better handling and displaying of skipped messages
|
||||||
• Various enhancements of the import process related to parsing
|
• Improved error reporting
|
||||||
• Cosmetic GUI changes
|
|
||||||
• Better error handling
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user