forked from Silverfish/proton-bridge
Other: add straightforward linters
This commit is contained in:
@ -52,7 +52,6 @@ linters:
|
|||||||
- funlen # Tool for detection of long functions [fast: true, auto-fix: false]
|
- funlen # Tool for detection of long functions [fast: true, auto-fix: false]
|
||||||
- gochecknoglobals # Checks that no globals are present in Go code [fast: true, auto-fix: false]
|
- gochecknoglobals # Checks that no globals are present in Go code [fast: true, auto-fix: false]
|
||||||
- gochecknoinits # Checks that no init functions are present in Go code [fast: true, auto-fix: false]
|
- gochecknoinits # Checks that no init functions are present in Go code [fast: true, auto-fix: false]
|
||||||
# - gocognit # Computes and checks the cognitive complexity of functions [fast: true, auto-fix: false]
|
|
||||||
- goconst # Finds repeated strings that could be replaced by a constant [fast: true, auto-fix: false]
|
- goconst # Finds repeated strings that could be replaced by a constant [fast: true, auto-fix: false]
|
||||||
- gocritic # The most opinionated Go source code linter [fast: true, auto-fix: false]
|
- gocritic # The most opinionated Go source code linter [fast: true, auto-fix: false]
|
||||||
- gocyclo # Computes and checks the cyclomatic complexity of functions [fast: true, auto-fix: false]
|
- gocyclo # Computes and checks the cyclomatic complexity of functions [fast: true, auto-fix: false]
|
||||||
@ -68,46 +67,45 @@ linters:
|
|||||||
- unconvert # Remove unnecessary type conversions [fast: true, auto-fix: false]
|
- unconvert # Remove unnecessary type conversions [fast: true, auto-fix: false]
|
||||||
- unparam # Reports unused function parameters [fast: true, auto-fix: false]
|
- unparam # Reports unused function parameters [fast: true, auto-fix: false]
|
||||||
- whitespace # Tool for detection of leading and trailing whitespace [fast: true, auto-fix: true]
|
- whitespace # Tool for detection of leading and trailing whitespace [fast: true, auto-fix: true]
|
||||||
|
- asciicheck # Simple linter to check that your code does not contain non-ASCII identifiers [fast: true, auto-fix: false]
|
||||||
|
- durationcheck # check for two durations multiplied together [fast: false, auto-fix: false]
|
||||||
|
- exhaustive # check exhaustiveness of enum switch statements [fast: false, auto-fix: false]
|
||||||
|
- exportloopref # checks for pointers to enclosing loop variables [fast: false, auto-fix: false]
|
||||||
|
- forcetypeassert # finds forced type assertions [fast: true, auto-fix: false]
|
||||||
|
- godot # Check if comments end in a period [fast: true, auto-fix: true]
|
||||||
|
- goheader # Checks is file header matches to pattern [fast: true, auto-fix: false]
|
||||||
|
- gomodguard # Allow and block list linter for direct Go module dependencies. This is different from depguard where there are different block types for example version constraints and module recommendations. [fast: true, auto-fix: false]
|
||||||
|
- goprintffuncname # Checks that printf-like functions are named with `f` at the end [fast: true, auto-fix: false]
|
||||||
|
- importas # Enforces consistent import aliases [fast: false, auto-fix: false]
|
||||||
|
- makezero # Finds slice declarations with non-zero initial length [fast: false, auto-fix: false]
|
||||||
|
- nilerr # Finds the code that returns nil even if it checks that the error is not nil. [fast: false, auto-fix: false]
|
||||||
|
- predeclared # find code that shadows one of Go's predeclared identifiers [fast: true, auto-fix: false]
|
||||||
|
- revive # Fast, configurable, extensible, flexible, and beautiful linter for Go. Drop-in replacement of golint. [fast: false, auto-fix: false]
|
||||||
|
- rowserrcheck # checks whether Err of rows is checked successfully [fast: false, auto-fix: false]
|
||||||
|
- sqlclosecheck # Checks that sql.Rows and sql.Stmt are closed. [fast: false, auto-fix: false]
|
||||||
|
- tparallel # tparallel detects inappropriate usage of t.Parallel() method in your Go test codes [fast: false, auto-fix: false]
|
||||||
|
- wastedassign # wastedassign finds wasted assignment statements. [fast: false, auto-fix: false]
|
||||||
# - wsl # Whitespace Linter - Forces you to use empty lines! [fast: true, auto-fix: false]
|
# - wsl # Whitespace Linter - Forces you to use empty lines! [fast: true, auto-fix: false]
|
||||||
# - lll # Reports long lines [fast: true, auto-fix: false]
|
# - lll # Reports long lines [fast: true, auto-fix: false]
|
||||||
# Newly added linters (not processed yet)
|
# Consider to include:
|
||||||
# - asciicheck # Simple linter to check that your code does not contain non-ASCII identifiers [fast: true, auto-fix: false]
|
# - gocognit # Computes and checks the cognitive complexity of functions [fast: true, auto-fix: false]
|
||||||
# - cyclop # checks function and package cyclomatic complexity [fast: false, auto-fix: false]
|
# - cyclop # checks function and package cyclomatic complexity [fast: false, auto-fix: false]
|
||||||
# - durationcheck # check for two durations multiplied together [fast: false, auto-fix: false]
|
|
||||||
# - errorlint # go-errorlint is a source code linter for Go software that can be used to find code that will cause problems with the error wrapping scheme introduced in Go 1.13. [fast: false, auto-fix: false]
|
# - errorlint # go-errorlint is a source code linter for Go software that can be used to find code that will cause problems with the error wrapping scheme introduced in Go 1.13. [fast: false, auto-fix: false]
|
||||||
# - exhaustive # check exhaustiveness of enum switch statements [fast: false, auto-fix: false]
|
|
||||||
# - exhaustivestruct # Checks if all struct's fields are initialized [fast: false, auto-fix: false]
|
# - exhaustivestruct # Checks if all struct's fields are initialized [fast: false, auto-fix: false]
|
||||||
# - exportloopref # checks for pointers to enclosing loop variables [fast: false, auto-fix: false]
|
|
||||||
# - forbidigo # Forbids identifiers [fast: true, auto-fix: false]
|
# - forbidigo # Forbids identifiers [fast: true, auto-fix: false]
|
||||||
# - forcetypeassert # finds forced type assertions [fast: true, auto-fix: false]
|
|
||||||
# - gci # Gci control golang package import order and make it always deterministic. [fast: true, auto-fix: true]
|
# - gci # Gci control golang package import order and make it always deterministic. [fast: true, auto-fix: true]
|
||||||
# - gocognit # Computes and checks the cognitive complexity of functions [fast: true, auto-fix: false]
|
# - gocognit # Computes and checks the cognitive complexity of functions [fast: true, auto-fix: false]
|
||||||
# - godot # Check if comments end in a period [fast: true, auto-fix: true]
|
|
||||||
# - goerr113 # Golang linter to check the errors handling expressions [fast: false, auto-fix: false]
|
# - goerr113 # Golang linter to check the errors handling expressions [fast: false, auto-fix: false]
|
||||||
# - gofumpt # Gofumpt checks whether code was gofumpt-ed. [fast: true, auto-fix: true]
|
# - gofumpt # Gofumpt checks whether code was gofumpt-ed. [fast: true, auto-fix: true]
|
||||||
# - goheader # Checks is file header matches to pattern [fast: true, auto-fix: false]
|
|
||||||
# - gomnd # An analyzer to detect magic numbers. [fast: true, auto-fix: false]
|
# - gomnd # An analyzer to detect magic numbers. [fast: true, auto-fix: false]
|
||||||
# - gomoddirectives # Manage the use of 'replace', 'retract', and 'excludes' directives in go.mod. [fast: true, auto-fix: false]
|
# - gomoddirectives # Manage the use of 'replace', 'retract', and 'excludes' directives in go.mod. [fast: true, auto-fix: false]
|
||||||
# - gomodguard # Allow and block list linter for direct Go module dependencies. This is different from depguard where there are different block types for example version constraints and module recommendations. [fast: true, auto-fix: false]
|
|
||||||
# - goprintffuncname # Checks that printf-like functions are named with `f` at the end [fast: true, auto-fix: false]
|
|
||||||
# - ifshort # Checks that your code uses short syntax for if-statements whenever possible [fast: true, auto-fix: false]
|
# - ifshort # Checks that your code uses short syntax for if-statements whenever possible [fast: true, auto-fix: false]
|
||||||
# - importas # Enforces consistent import aliases [fast: false, auto-fix: false]
|
|
||||||
# - lll # Reports long lines [fast: true, auto-fix: false]
|
|
||||||
# - makezero # Finds slice declarations with non-zero initial length [fast: false, auto-fix: false]
|
|
||||||
# - nestif # Reports deeply nested if statements [fast: true, auto-fix: false]
|
# - nestif # Reports deeply nested if statements [fast: true, auto-fix: false]
|
||||||
# - nilerr # Finds the code that returns nil even if it checks that the error is not nil. [fast: false, auto-fix: false]
|
|
||||||
# - nlreturn # nlreturn checks for a new line before return and branch statements to increase code clarity [fast: true, auto-fix: false]
|
# - nlreturn # nlreturn checks for a new line before return and branch statements to increase code clarity [fast: true, auto-fix: false]
|
||||||
# - noctx # noctx finds sending http request without context.Context [fast: false, auto-fix: false]
|
# - noctx # noctx finds sending http request without context.Context [fast: false, auto-fix: false]
|
||||||
# - nolintlint # Reports ill-formed or insufficient nolint directives [fast: true, auto-fix: false]
|
# - nolintlint # Reports ill-formed or insufficient nolint directives [fast: true, auto-fix: false]
|
||||||
# - paralleltest # paralleltest detects missing usage of t.Parallel() method in your Go test [fast: true, auto-fix: false]
|
# - paralleltest # paralleltest detects missing usage of t.Parallel() method in your Go test [fast: true, auto-fix: false]
|
||||||
# - predeclared # find code that shadows one of Go's predeclared identifiers [fast: true, auto-fix: false]
|
|
||||||
# - revive # Fast, configurable, extensible, flexible, and beautiful linter for Go. Drop-in replacement of golint. [fast: false, auto-fix: false]
|
|
||||||
# - rowserrcheck # checks whether Err of rows is checked successfully [fast: false, auto-fix: false]
|
|
||||||
# - sqlclosecheck # Checks that sql.Rows and sql.Stmt are closed. [fast: false, auto-fix: false]
|
|
||||||
# - testpackage # linter that makes you use a separate _test package [fast: true, auto-fix: false]
|
# - testpackage # linter that makes you use a separate _test package [fast: true, auto-fix: false]
|
||||||
# - thelper # thelper detects golang test helpers without t.Helper() call and checks the consistency of test helpers [fast: false, auto-fix: false]
|
# - thelper # thelper detects golang test helpers without t.Helper() call and checks the consistency of test helpers [fast: false, auto-fix: false]
|
||||||
# - tparallel # tparallel detects inappropriate usage of t.Parallel() method in your Go test codes [fast: false, auto-fix: false]
|
|
||||||
# - wastedassign # wastedassign finds wasted assignment statements. [fast: false, auto-fix: false]
|
|
||||||
# - wrapcheck # Checks that errors returned from external packages are wrapped [fast: false, auto-fix: false]
|
# - wrapcheck # Checks that errors returned from external packages are wrapped [fast: false, auto-fix: false]
|
||||||
# - wsl # Whitespace Linter - Forces you to use empty lines! [fast: true, auto-fix: false]
|
|
||||||
|
|
||||||
|
|||||||
@ -69,7 +69,7 @@ const (
|
|||||||
flagMemProfileShort = "m"
|
flagMemProfileShort = "m"
|
||||||
flagLogLevel = "log-level"
|
flagLogLevel = "log-level"
|
||||||
flagLogLevelShort = "l"
|
flagLogLevelShort = "l"
|
||||||
// FlagCLI indicate to start with command line interface
|
// FlagCLI indicate to start with command line interface.
|
||||||
FlagCLI = "cli"
|
FlagCLI = "cli"
|
||||||
flagCLIShort = "c"
|
flagCLIShort = "c"
|
||||||
flagRestart = "restart"
|
flagRestart = "restart"
|
||||||
|
|||||||
@ -34,7 +34,7 @@ import (
|
|||||||
// | prefs | ~/.cache/protonmail/<app>/c11/prefs.json | ~/.config/protonmail/<app>/prefs.json |
|
// | prefs | ~/.cache/protonmail/<app>/c11/prefs.json | ~/.config/protonmail/<app>/prefs.json |
|
||||||
// | c11 1.5.x | ~/.cache/protonmail/<app>/c11 | ~/.cache/protonmail/<app>/cache/c11 |
|
// | c11 1.5.x | ~/.cache/protonmail/<app>/c11 | ~/.cache/protonmail/<app>/cache/c11 |
|
||||||
// | c11 1.6.x | ~/.cache/protonmail/<app>/cache/c11 | ~/.config/protonmail/<app>/cache/c11 |
|
// | c11 1.6.x | ~/.cache/protonmail/<app>/cache/c11 | ~/.config/protonmail/<app>/cache/c11 |
|
||||||
// | updates | ~/.cache/protonmail/<app>/updates | ~/.config/protonmail/<app>/updates |
|
// | updates | ~/.cache/protonmail/<app>/updates | ~/.config/protonmail/<app>/updates |.
|
||||||
func migrateFiles(configName string) error {
|
func migrateFiles(configName string) error {
|
||||||
locationsProvider, err := locations.NewDefaultProvider(filepath.Join(constants.VendorName, configName))
|
locationsProvider, err := locations.NewDefaultProvider(filepath.Join(constants.VendorName, configName))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -50,7 +50,7 @@ func migrateFiles(configName string) error {
|
|||||||
if err := migrateCacheFromBoth15xAnd16x(locations, userCacheDir); err != nil {
|
if err := migrateCacheFromBoth15xAnd16x(locations, userCacheDir); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := migrateUpdatesFrom16x(configName, locations); err != nil {
|
if err := migrateUpdatesFrom16x(configName, locations); err != nil { //nolint[revive] It is more clear to structure this way
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@ -122,11 +122,7 @@ func (t *TLS) GenerateCerts(template *x509.Certificate) error {
|
|||||||
}
|
}
|
||||||
defer keyOut.Close() // nolint[errcheck]
|
defer keyOut.Close() // nolint[errcheck]
|
||||||
|
|
||||||
if err := pem.Encode(keyOut, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(priv)}); err != nil {
|
return pem.Encode(keyOut, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(priv)})
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetConfig tries to load TLS config or generate new one which is then returned.
|
// GetConfig tries to load TLS config or generate new one which is then returned.
|
||||||
|
|||||||
@ -26,7 +26,7 @@ type currentClientSetter interface {
|
|||||||
SetClient(name, version string)
|
SetClient(name, version string)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extension for IMAP server
|
// Extension for IMAP server.
|
||||||
type extension struct {
|
type extension struct {
|
||||||
extID imapserver.ConnExtension
|
extID imapserver.ConnExtension
|
||||||
clientSetter currentClientSetter
|
clientSetter currentClientSetter
|
||||||
|
|||||||
@ -227,7 +227,8 @@ func (im *imapMailbox) importMessage(m *pmapi.Message, readers []io.Reader, kr *
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (im *imapMailbox) getMessage(storeMessage storeMessageProvider, items []imap.FetchItem, msgBuildCountHistogram *msgBuildCountHistogram) (msg *imap.Message, err error) { //nolint[funlen]
|
func (im *imapMailbox) getMessage(storeMessage storeMessageProvider, items []imap.FetchItem, msgBuildCountHistogram *msgBuildCountHistogram) (msg *imap.Message, err error) { //nolint[funlen]
|
||||||
im.log.WithField("msgID", storeMessage.ID()).Trace("Getting message")
|
msglog := im.log.WithField("msgID", storeMessage.ID())
|
||||||
|
msglog.Trace("Getting message")
|
||||||
|
|
||||||
seqNum, err := storeMessage.SequenceNumber()
|
seqNum, err := storeMessage.SequenceNumber()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -267,7 +268,7 @@ func (im *imapMailbox) getMessage(storeMessage storeMessageProvider, items []ima
|
|||||||
// Size attribute on the server counts encrypted data. The value is cleared
|
// Size attribute on the server counts encrypted data. The value is cleared
|
||||||
// on our part and we need to compute "real" size of decrypted data.
|
// on our part and we need to compute "real" size of decrypted data.
|
||||||
if m.Size <= 0 {
|
if m.Size <= 0 {
|
||||||
im.log.WithField("msgID", storeMessage.ID()).Trace("Size unknown - downloading body")
|
msglog.Debug("Size unknown - downloading body")
|
||||||
// We are sure the size is not a problem right now. Clients
|
// We are sure the size is not a problem right now. Clients
|
||||||
// might not first check sizes of all messages so we couldn't
|
// might not first check sizes of all messages so we couldn't
|
||||||
// be sure if seeing 1st or 2nd sync is all right or not.
|
// be sure if seeing 1st or 2nd sync is all right or not.
|
||||||
@ -283,6 +284,8 @@ func (im *imapMailbox) getMessage(storeMessage storeMessageProvider, items []ima
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
case imap.FetchAll, imap.FetchFast, imap.FetchFull, imap.FetchRFC822, imap.FetchRFC822Header, imap.FetchRFC822Text:
|
||||||
|
fallthrough // this is list of defined items by go-imap, but items can be also sections generated from requests
|
||||||
default:
|
default:
|
||||||
if err = im.getLiteralForSection(item, msg, storeMessage, msgBuildCountHistogram); err != nil {
|
if err = im.getLiteralForSection(item, msg, storeMessage, msgBuildCountHistogram); err != nil {
|
||||||
return
|
return
|
||||||
@ -295,8 +298,8 @@ func (im *imapMailbox) getMessage(storeMessage storeMessageProvider, items []ima
|
|||||||
|
|
||||||
func (im *imapMailbox) getLiteralForSection(itemSection imap.FetchItem, msg *imap.Message, storeMessage storeMessageProvider, msgBuildCountHistogram *msgBuildCountHistogram) error {
|
func (im *imapMailbox) getLiteralForSection(itemSection imap.FetchItem, msg *imap.Message, storeMessage storeMessageProvider, msgBuildCountHistogram *msgBuildCountHistogram) error {
|
||||||
section, err := imap.ParseBodySectionName(itemSection)
|
section, err := imap.ParseBodySectionName(itemSection)
|
||||||
if err != nil { // Ignore error
|
if err != nil {
|
||||||
return nil
|
return nil //nolint[nilerr] ignore error
|
||||||
}
|
}
|
||||||
|
|
||||||
var literal imap.Literal
|
var literal imap.Literal
|
||||||
@ -743,7 +746,7 @@ func (im *imapMailbox) buildMessageInner(m *pmapi.Message, kr *crypto.KeyRing) (
|
|||||||
}
|
}
|
||||||
|
|
||||||
processCallback := func(value interface{}) (interface{}, error) {
|
processCallback := func(value interface{}) (interface{}, error) {
|
||||||
att := value.(*pmapi.Attachment)
|
att := value.(*pmapi.Attachment) //nolint[forcetypeassert] we want to panic here
|
||||||
|
|
||||||
buf := &bytes.Buffer{}
|
buf := &bytes.Buffer{}
|
||||||
if err = im.writeAttachmentBody(buf, m, att); err != nil {
|
if err = im.writeAttachmentBody(buf, m, att); err != nil {
|
||||||
@ -753,7 +756,7 @@ func (im *imapMailbox) buildMessageInner(m *pmapi.Message, kr *crypto.KeyRing) (
|
|||||||
}
|
}
|
||||||
|
|
||||||
collectCallback := func(idx int, value interface{}) error {
|
collectCallback := func(idx int, value interface{}) error {
|
||||||
buf := value.(*bytes.Buffer)
|
buf := value.(*bytes.Buffer) //nolint[forcetypeassert] we want to panic here
|
||||||
defer buf.Reset()
|
defer buf.Reset()
|
||||||
att := atts[idx]
|
att := atts[idx]
|
||||||
|
|
||||||
|
|||||||
@ -141,7 +141,7 @@ func (im *imapMailbox) addOrRemoveFlags(operation imap.FlagsOp, messageIDs, flag
|
|||||||
for _, f := range flags {
|
for _, f := range flags {
|
||||||
switch f {
|
switch f {
|
||||||
case imap.SeenFlag:
|
case imap.SeenFlag:
|
||||||
switch operation {
|
switch operation { //nolint[exhaustive] imap.SetFlags is processed by im.setFlags
|
||||||
case imap.AddFlags:
|
case imap.AddFlags:
|
||||||
if err := im.storeMailbox.MarkMessagesRead(messageIDs); err != nil {
|
if err := im.storeMailbox.MarkMessagesRead(messageIDs); err != nil {
|
||||||
return err
|
return err
|
||||||
@ -152,7 +152,7 @@ func (im *imapMailbox) addOrRemoveFlags(operation imap.FlagsOp, messageIDs, flag
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
case imap.FlaggedFlag:
|
case imap.FlaggedFlag:
|
||||||
switch operation {
|
switch operation { //nolint[exhaustive] imap.SetFlag is processed by im.setFlags
|
||||||
case imap.AddFlags:
|
case imap.AddFlags:
|
||||||
if err := im.storeMailbox.MarkMessagesStarred(messageIDs); err != nil {
|
if err := im.storeMailbox.MarkMessagesStarred(messageIDs); err != nil {
|
||||||
return err
|
return err
|
||||||
@ -163,7 +163,7 @@ func (im *imapMailbox) addOrRemoveFlags(operation imap.FlagsOp, messageIDs, flag
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
case imap.DeletedFlag:
|
case imap.DeletedFlag:
|
||||||
switch operation {
|
switch operation { //nolint[exhaustive] imap.SetFlag is processed by im.setFlags
|
||||||
case imap.AddFlags:
|
case imap.AddFlags:
|
||||||
if err := im.storeMailbox.MarkMessagesDeleted(messageIDs); err != nil {
|
if err := im.storeMailbox.MarkMessagesDeleted(messageIDs); err != nil {
|
||||||
return err
|
return err
|
||||||
@ -182,7 +182,7 @@ func (im *imapMailbox) addOrRemoveFlags(operation imap.FlagsOp, messageIDs, flag
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Handle custom junk flags for Apple Mail and Thunderbird.
|
// Handle custom junk flags for Apple Mail and Thunderbird.
|
||||||
switch operation {
|
switch operation { //nolint[exhaustive] imap.SetFlag is processed by im.setFlags
|
||||||
// No label removal is necessary because Spam and Inbox are both exclusive labels so the backend
|
// No label removal is necessary because Spam and Inbox are both exclusive labels so the backend
|
||||||
// will automatically take care of label removal.
|
// will automatically take care of label removal.
|
||||||
case imap.AddFlags:
|
case imap.AddFlags:
|
||||||
@ -536,7 +536,7 @@ func (im *imapMailbox) listMessages(isUID bool, seqSet *imap.SeqSet, items []ima
|
|||||||
}
|
}
|
||||||
|
|
||||||
processCallback := func(value interface{}) (interface{}, error) {
|
processCallback := func(value interface{}) (interface{}, error) {
|
||||||
apiID := value.(string)
|
apiID := value.(string) //nolint[forcetypeassert] we want to panic here
|
||||||
|
|
||||||
storeMessage, err := im.storeMailbox.GetMessage(apiID)
|
storeMessage, err := im.storeMailbox.GetMessage(apiID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -570,7 +570,7 @@ func (im *imapMailbox) listMessages(isUID bool, seqSet *imap.SeqSet, items []ima
|
|||||||
}
|
}
|
||||||
|
|
||||||
collectCallback := func(idx int, value interface{}) error {
|
collectCallback := func(idx int, value interface{}) error {
|
||||||
msg := value.(*imap.Message)
|
msg := value.(*imap.Message) //nolint[forcetypeassert] we want to panic here
|
||||||
msgResponse <- msg
|
msgResponse <- msg
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -32,7 +32,7 @@ import (
|
|||||||
// - 100 messages were downloaded first time
|
// - 100 messages were downloaded first time
|
||||||
// - 100 messages were downloaded second time
|
// - 100 messages were downloaded second time
|
||||||
// - 99 messages were downloaded 10th times
|
// - 99 messages were downloaded 10th times
|
||||||
// - 1 messages were downloaded 100th times
|
// - 1 messages were downloaded 100th times.
|
||||||
type msgBuildCountHistogram struct {
|
type msgBuildCountHistogram struct {
|
||||||
// Key represents how many times message was build.
|
// Key represents how many times message was build.
|
||||||
// Value stores how many messages are build X times based on the key.
|
// Value stores how many messages are build X times based on the key.
|
||||||
|
|||||||
@ -33,7 +33,7 @@ import (
|
|||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Capability extension identifier
|
// Capability extension identifier.
|
||||||
const Capability = "UIDPLUS"
|
const Capability = "UIDPLUS"
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -228,7 +228,9 @@ func getStatusResponseCopy(uidValidity uint32, sourceSeq, targetSeq *OrderedSeq)
|
|||||||
|
|
||||||
// CopyResponse prepares OK response with extended UID information about copied message.
|
// CopyResponse prepares OK response with extended UID information about copied message.
|
||||||
func CopyResponse(uidValidity uint32, sourceSeq, targetSeq *OrderedSeq) error {
|
func CopyResponse(uidValidity uint32, sourceSeq, targetSeq *OrderedSeq) error {
|
||||||
return imap.ErrStatusResp{getStatusResponseCopy(uidValidity, sourceSeq, targetSeq)}
|
return &imap.ErrStatusResp{
|
||||||
|
Resp: getStatusResponseCopy(uidValidity, sourceSeq, targetSeq),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func getStatusResponseAppend(uidValidity uint32, targetSeq *OrderedSeq) *imap.StatusResp {
|
func getStatusResponseAppend(uidValidity uint32, targetSeq *OrderedSeq) *imap.StatusResp {
|
||||||
@ -250,5 +252,7 @@ func getStatusResponseAppend(uidValidity uint32, targetSeq *OrderedSeq) *imap.St
|
|||||||
|
|
||||||
// AppendResponse prepares OK response with extended UID information about appended message.
|
// AppendResponse prepares OK response with extended UID information about appended message.
|
||||||
func AppendResponse(uidValidity uint32, targetSeq *OrderedSeq) error {
|
func AppendResponse(uidValidity uint32, targetSeq *OrderedSeq) error {
|
||||||
return imap.ErrStatusResp{getStatusResponseAppend(uidValidity, targetSeq)}
|
return &imap.ErrStatusResp{
|
||||||
|
Resp: getStatusResponseAppend(uidValidity, targetSeq),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -88,7 +88,7 @@ func (ie *ImportExport) ReportBug(osType, osVersion, description, accountName, a
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReportFile submits import report file
|
// ReportFile submits import report file.
|
||||||
func (ie *ImportExport) ReportFile(osType, osVersion, accountName, address string, logdata []byte) error {
|
func (ie *ImportExport) ReportFile(osType, osVersion, accountName, address string, logdata []byte) error {
|
||||||
c := ie.clientManager.GetAnonymousClient()
|
c := ie.clientManager.GetAnonymousClient()
|
||||||
defer c.Logout()
|
defer c.Logout()
|
||||||
|
|||||||
@ -34,7 +34,7 @@ import (
|
|||||||
// - logs: ~/.cache/protonmail/<app>/logs
|
// - logs: ~/.cache/protonmail/<app>/logs
|
||||||
// - cache: ~/.config/protonmail/<app>/cache
|
// - cache: ~/.config/protonmail/<app>/cache
|
||||||
// - updates: ~/.config/protonmail/<app>/updates
|
// - updates: ~/.config/protonmail/<app>/updates
|
||||||
// - lockfile: ~/.cache/protonmail/<app>/<app>.lock
|
// - lockfile: ~/.cache/protonmail/<app>/<app>.lock .
|
||||||
type Locations struct {
|
type Locations struct {
|
||||||
userConfig, userCache string
|
userConfig, userCache string
|
||||||
configName string
|
configName string
|
||||||
|
|||||||
@ -173,7 +173,7 @@ func (b *sendPreferencesBuilder) withPublicKey(v *crypto.KeyRing) {
|
|||||||
// | 16 (PGP/MIME),
|
// | 16 (PGP/MIME),
|
||||||
// mimeType: 'text/html' | 'text/plain' | 'multipart/mixed',
|
// mimeType: 'text/html' | 'text/plain' | 'multipart/mixed',
|
||||||
// publicKey: OpenPGPKey | undefined/null
|
// publicKey: OpenPGPKey | undefined/null
|
||||||
// }
|
// }.
|
||||||
func (b *sendPreferencesBuilder) build() (p SendPreferences) {
|
func (b *sendPreferencesBuilder) build() (p SendPreferences) {
|
||||||
p.Encrypt = b.shouldEncrypt()
|
p.Encrypt = b.shouldEncrypt()
|
||||||
p.Sign = b.shouldSign()
|
p.Sign = b.shouldSign()
|
||||||
@ -492,6 +492,8 @@ func (b *sendPreferencesBuilder) setEncryptionPreferences(mailSettings pmapi.Mai
|
|||||||
b.withSchemeDefault(pgpInline)
|
b.withSchemeDefault(pgpInline)
|
||||||
case pmapi.PGPMIMEPackage:
|
case pmapi.PGPMIMEPackage:
|
||||||
b.withSchemeDefault(pgpMIME)
|
b.withSchemeDefault(pgpMIME)
|
||||||
|
case pmapi.ClearMIMEPackage, pmapi.ClearPackage, pmapi.EncryptedOutsidePackage, pmapi.InternalPackage:
|
||||||
|
// nothing to set
|
||||||
}
|
}
|
||||||
|
|
||||||
// Its value is constrained by the sign flag and the PGP scheme:
|
// Its value is constrained by the sign flag and the PGP scheme:
|
||||||
|
|||||||
@ -156,6 +156,7 @@ func (loop *eventLoop) loop() {
|
|||||||
return
|
return
|
||||||
case <-t.C:
|
case <-t.C:
|
||||||
// Randomise periodic calls within range pollInterval ± pollSpread to reduces potential load spikes on API.
|
// Randomise periodic calls within range pollInterval ± pollSpread to reduces potential load spikes on API.
|
||||||
|
//nolint[gosec] It is OK to use weaker random number generator here
|
||||||
time.Sleep(time.Duration(rand.Intn(2*int(pollIntervalSpread.Milliseconds()))) * time.Millisecond)
|
time.Sleep(time.Duration(rand.Intn(2*int(pollIntervalSpread.Milliseconds()))) * time.Millisecond)
|
||||||
case eventProcessedCh = <-loop.pollCh:
|
case eventProcessedCh = <-loop.pollCh:
|
||||||
// We don't want to wait here. Polling should happen instantly.
|
// We don't want to wait here. Polling should happen instantly.
|
||||||
@ -381,6 +382,8 @@ func (loop *eventLoop) processAddresses(log *logrus.Entry, addressEvents []*pmap
|
|||||||
log.WithField("email", email).Debug("Address was deleted")
|
log.WithField("email", email).Debug("Address was deleted")
|
||||||
loop.user.CloseConnection(email)
|
loop.user.CloseConnection(email)
|
||||||
loop.events.Emit(bridgeEvents.AddressChangedLogoutEvent, email)
|
loop.events.Emit(bridgeEvents.AddressChangedLogoutEvent, email)
|
||||||
|
case pmapi.EventUpdateFlags:
|
||||||
|
log.Error("EventUpdateFlags for address event is uknown operation")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -409,6 +412,8 @@ func (loop *eventLoop) processLabels(eventLog *logrus.Entry, labels []*pmapi.Eve
|
|||||||
if err := loop.store.deleteMailboxEvent(eventLabel.ID); err != nil {
|
if err := loop.store.deleteMailboxEvent(eventLabel.ID); err != nil {
|
||||||
return errors.Wrap(err, "failed to delete label")
|
return errors.Wrap(err, "failed to delete label")
|
||||||
}
|
}
|
||||||
|
case pmapi.EventUpdateFlags:
|
||||||
|
log.Error("EventUpdateFlags for label event is uknown operation")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -254,7 +254,7 @@ func (storeMailbox *Mailbox) txGetAPIIDsBucket(tx *bolt.Tx) *bolt.Bucket {
|
|||||||
return storeMailbox.txGetBucket(tx).Bucket(apiIDsBucket)
|
return storeMailbox.txGetBucket(tx).Bucket(apiIDsBucket)
|
||||||
}
|
}
|
||||||
|
|
||||||
// txGetDeletedIDsBucket returns the bucket with messagesID marked as deleted
|
// txGetDeletedIDsBucket returns the bucket with messagesID marked as deleted.
|
||||||
func (storeMailbox *Mailbox) txGetDeletedIDsBucket(tx *bolt.Tx) *bolt.Bucket {
|
func (storeMailbox *Mailbox) txGetDeletedIDsBucket(tx *bolt.Tx) *bolt.Bucket {
|
||||||
return storeMailbox.txGetBucket(tx).Bucket(deletedIDsBucket)
|
return storeMailbox.txGetBucket(tx).Bucket(deletedIDsBucket)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -25,7 +25,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// ErrAllMailOpNotAllowed is error user when user tries to do unsupported
|
// ErrAllMailOpNotAllowed is error user when user tries to do unsupported
|
||||||
// operation on All Mail folder
|
// operation on All Mail folder.
|
||||||
var ErrAllMailOpNotAllowed = errors.New("operation not allowed for 'All Mail' folder")
|
var ErrAllMailOpNotAllowed = errors.New("operation not allowed for 'All Mail' folder")
|
||||||
|
|
||||||
// GetMessage returns the `pmapi.Message` struct wrapped in `StoreMessage`
|
// GetMessage returns the `pmapi.Message` struct wrapped in `StoreMessage`
|
||||||
@ -177,7 +177,7 @@ func (storeMailbox *Mailbox) MarkMessagesUnstarred(apiIDs []string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// MarkMessagesDeleted adds local flag \Deleted. This is not propagated to API
|
// MarkMessagesDeleted adds local flag \Deleted. This is not propagated to API
|
||||||
// until RemoveDeleted is called
|
// until RemoveDeleted is called.
|
||||||
func (storeMailbox *Mailbox) MarkMessagesDeleted(apiIDs []string) error {
|
func (storeMailbox *Mailbox) MarkMessagesDeleted(apiIDs []string) error {
|
||||||
log.WithFields(logrus.Fields{
|
log.WithFields(logrus.Fields{
|
||||||
"messages": apiIDs,
|
"messages": apiIDs,
|
||||||
|
|||||||
@ -64,7 +64,7 @@ func (message *Message) Message() *pmapi.Message {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// IsMarkedDeleted returns true if message is marked as deleted for specific
|
// IsMarkedDeleted returns true if message is marked as deleted for specific
|
||||||
// mailbox
|
// mailbox.
|
||||||
func (message *Message) IsMarkedDeleted() bool {
|
func (message *Message) IsMarkedDeleted() bool {
|
||||||
isMarkedAsDeleted := false
|
isMarkedAsDeleted := false
|
||||||
err := message.storeMailbox.db().View(func(tx *bolt.Tx) error {
|
err := message.storeMailbox.db().View(func(tx *bolt.Tx) error {
|
||||||
|
|||||||
@ -34,15 +34,15 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// PathDelimiter for IMAP
|
// PathDelimiter for IMAP.
|
||||||
PathDelimiter = "/"
|
PathDelimiter = "/"
|
||||||
// UserLabelsMailboxName for IMAP
|
// UserLabelsMailboxName for IMAP.
|
||||||
UserLabelsMailboxName = "Labels"
|
UserLabelsMailboxName = "Labels"
|
||||||
// UserLabelsPrefix contains name with delimiter for IMAP
|
// UserLabelsPrefix contains name with delimiter for IMAP.
|
||||||
UserLabelsPrefix = UserLabelsMailboxName + PathDelimiter
|
UserLabelsPrefix = UserLabelsMailboxName + PathDelimiter
|
||||||
// UserFoldersMailboxName for IMAP
|
// UserFoldersMailboxName for IMAP.
|
||||||
UserFoldersMailboxName = "Folders"
|
UserFoldersMailboxName = "Folders"
|
||||||
// UserFoldersPrefix contains name with delimiter for IMAP
|
// UserFoldersPrefix contains name with delimiter for IMAP.
|
||||||
UserFoldersPrefix = UserFoldersMailboxName + PathDelimiter
|
UserFoldersPrefix = UserFoldersMailboxName + PathDelimiter
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@ -90,10 +90,7 @@ func (store *Store) TestDumpDB(tb assert.TestingT) {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err := txMails(tx); err != nil {
|
return txMails(tx)
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
assert.NoError(tb, store.db.View(txDump))
|
assert.NoError(tb, store.db.View(txDump))
|
||||||
|
|||||||
@ -289,7 +289,7 @@ func clearNonMetadata(onlyMeta *pmapi.Message) {
|
|||||||
// If there is stored message in metaBucket the size, header and MIMEType are
|
// If there is stored message in metaBucket the size, header and MIMEType are
|
||||||
// not changed if already set. To change these:
|
// not changed if already set. To change these:
|
||||||
// * size must be updated by Message.SetSize
|
// * size must be updated by Message.SetSize
|
||||||
// * contentType and header must be updated by Message.SetContentTypeAndHeader
|
// * contentType and header must be updated by Message.SetContentTypeAndHeader.
|
||||||
func txUpdateMetadaFromDB(metaBucket *bolt.Bucket, onlyMeta *pmapi.Message, log *logrus.Entry) {
|
func txUpdateMetadaFromDB(metaBucket *bolt.Bucket, onlyMeta *pmapi.Message, log *logrus.Entry) {
|
||||||
// Size attribute on the server is counting encrypted data. We need to compute
|
// Size attribute on the server is counting encrypted data. We need to compute
|
||||||
// "real" size of decrypted data. Negative values will be processed during fetch.
|
// "real" size of decrypted data. Negative values will be processed during fetch.
|
||||||
|
|||||||
@ -35,7 +35,7 @@ var systemFolderMapping = map[string]string{ //nolint[gochecknoglobals]
|
|||||||
// Add more translations.
|
// Add more translations.
|
||||||
}
|
}
|
||||||
|
|
||||||
// LeastUsedColor is intended to return color for creating a new inbox or label
|
// LeastUsedColor is intended to return color for creating a new inbox or label.
|
||||||
func LeastUsedColor(mailboxes []Mailbox) string {
|
func LeastUsedColor(mailboxes []Mailbox) string {
|
||||||
usedColors := []string{}
|
usedColors := []string{}
|
||||||
for _, m := range mailboxes {
|
for _, m := range mailboxes {
|
||||||
|
|||||||
@ -27,7 +27,7 @@ import (
|
|||||||
|
|
||||||
type IMAPClientProvider interface {
|
type IMAPClientProvider interface {
|
||||||
Capability() (map[string]bool, error)
|
Capability() (map[string]bool, error)
|
||||||
Support(cap string) (bool, error)
|
Support(capability string) (bool, error)
|
||||||
State() imap.ConnState
|
State() imap.ConnState
|
||||||
SupportAuth(mech string) (bool, error)
|
SupportAuth(mech string) (bool, error)
|
||||||
Authenticate(auth sasl.Client) error
|
Authenticate(auth sasl.Client) error
|
||||||
|
|||||||
@ -329,10 +329,10 @@ func (p *PMAPIProvider) importMessage(msgSourceID string, progress *Progress, re
|
|||||||
}
|
}
|
||||||
if results[0].Error != nil {
|
if results[0].Error != nil {
|
||||||
importedErr = errors.Wrap(results[0].Error, "failed to import message")
|
importedErr = errors.Wrap(results[0].Error, "failed to import message")
|
||||||
return nil // Call passed but API refused this message, skip this one.
|
return nil //nolint[nilerr] Call passed but API refused this message, skip this one.
|
||||||
}
|
}
|
||||||
importedID = results[0].MessageID
|
importedID = results[0].MessageID
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
return
|
return importedID, importedErr
|
||||||
}
|
}
|
||||||
|
|||||||
@ -85,7 +85,7 @@ func testTransferFrom(t *testing.T, rules transferRules, provider TargetProvider
|
|||||||
progress.finish()
|
progress.finish()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
maxWait := time.Duration(len(messages)) * 2 * time.Second
|
maxWait := time.Duration(len(messages)*2) * time.Second
|
||||||
a.Eventually(t, func() bool {
|
a.Eventually(t, func() bool {
|
||||||
return progress.updateCh == nil
|
return progress.updateCh == nil
|
||||||
}, maxWait, 10*time.Millisecond, "Waiting for imported messages timed out")
|
}, maxWait, 10*time.Millisecond, "Waiting for imported messages timed out")
|
||||||
|
|||||||
@ -78,7 +78,7 @@ type VersionInfo struct {
|
|||||||
// "...": {
|
// "...": {
|
||||||
// ...
|
// ...
|
||||||
// }
|
// }
|
||||||
// }
|
// }.
|
||||||
type VersionMap map[string]VersionInfo
|
type VersionMap map[string]VersionInfo
|
||||||
|
|
||||||
// getVersionFileURL returns the URL of the version file.
|
// getVersionFileURL returns the URL of the version file.
|
||||||
|
|||||||
@ -67,7 +67,7 @@ func (s *testCredentials) MarshalGob() string {
|
|||||||
if err := enc.Encode(s); err != nil {
|
if err := enc.Encode(s); err != nil {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
fmt.Printf("MarshalGob: %#v\n", buf.String())
|
log.Infof("MarshalGob: %#v\n", buf.String())
|
||||||
return base64.StdEncoding.EncodeToString(buf.Bytes())
|
return base64.StdEncoding.EncodeToString(buf.Bytes())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,13 +88,13 @@ func (s *testCredentials) UnmarshalGob(secret string) error {
|
|||||||
s.Clear()
|
s.Clear()
|
||||||
b, err := base64.StdEncoding.DecodeString(secret)
|
b, err := base64.StdEncoding.DecodeString(secret)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("decode base64", b)
|
log.Infoln("decode base64", b)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
buf := bytes.NewBuffer(b)
|
buf := bytes.NewBuffer(b)
|
||||||
dec := gob.NewDecoder(buf)
|
dec := gob.NewDecoder(buf)
|
||||||
if err = dec.Decode(s); err != nil {
|
if err = dec.Decode(s); err != nil {
|
||||||
fmt.Println("decode gob", b, buf.Bytes())
|
log.Info("decode gob", b, buf.Bytes())
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@ -102,7 +102,7 @@ func (s *testCredentials) UnmarshalGob(secret string) error {
|
|||||||
|
|
||||||
func (s *testCredentials) ToJSON() string {
|
func (s *testCredentials) ToJSON() string {
|
||||||
if b, err := json.Marshal(s); err == nil {
|
if b, err := json.Marshal(s); err == nil {
|
||||||
fmt.Printf("MarshalJSON: %#v\n", string(b))
|
log.Infof("MarshalJSON: %#v\n", string(b))
|
||||||
return base64.StdEncoding.EncodeToString(b)
|
return base64.StdEncoding.EncodeToString(b)
|
||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
@ -134,7 +134,7 @@ func (s *testCredentials) MarshalFmt() string {
|
|||||||
s.IsHidden,
|
s.IsHidden,
|
||||||
s.IsCombinedAddressMode,
|
s.IsCombinedAddressMode,
|
||||||
)
|
)
|
||||||
fmt.Printf("MarshalFmt: %#v\n", buf.String())
|
log.Infof("MarshalFmt: %#v\n", buf.String())
|
||||||
return base64.StdEncoding.EncodeToString(buf.Bytes())
|
return base64.StdEncoding.EncodeToString(buf.Bytes())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -144,7 +144,7 @@ func (s *testCredentials) UnmarshalFmt(secret string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
buf := bytes.NewBuffer(b)
|
buf := bytes.NewBuffer(b)
|
||||||
fmt.Println("decode fmt", b, buf.Bytes())
|
log.Infoln("decode fmt", b, buf.Bytes())
|
||||||
_, err = fmt.Fscanf(
|
_, err = fmt.Fscanf(
|
||||||
buf, secretFormat,
|
buf, secretFormat,
|
||||||
&s.UserID,
|
&s.UserID,
|
||||||
@ -190,7 +190,7 @@ func (s *testCredentials) MarshalStrings() string { // this is the most space ef
|
|||||||
|
|
||||||
str := strings.Join(items, sep)
|
str := strings.Join(items, sep)
|
||||||
|
|
||||||
fmt.Printf("MarshalJoin: %#v\n", str)
|
log.Infof("MarshalJoin: %#v\n", str)
|
||||||
return base64.StdEncoding.EncodeToString([]byte(str))
|
return base64.StdEncoding.EncodeToString([]byte(str))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -237,37 +237,37 @@ func (s *testCredentials) IsSame(rhs *testCredentials) bool {
|
|||||||
|
|
||||||
func TestMarshalFormats(t *testing.T) {
|
func TestMarshalFormats(t *testing.T) {
|
||||||
input := testCredentials{UserID: "007", Emails: "ja@pm.me;jakub@cu.th", Timestamp: 152469263742, IsHidden: true}
|
input := testCredentials{UserID: "007", Emails: "ja@pm.me;jakub@cu.th", Timestamp: 152469263742, IsHidden: true}
|
||||||
fmt.Printf("input %#v\n", input)
|
log.Infof("input %#v\n", input)
|
||||||
|
|
||||||
secretStrings := input.MarshalStrings()
|
secretStrings := input.MarshalStrings()
|
||||||
fmt.Printf("secretStrings %#v %d\n", secretStrings, len(secretStrings))
|
log.Infof("secretStrings %#v %d\n", secretStrings, len(secretStrings))
|
||||||
secretGob := input.MarshalGob()
|
secretGob := input.MarshalGob()
|
||||||
fmt.Printf("secretGob %#v %d\n", secretGob, len(secretGob))
|
log.Infof("secretGob %#v %d\n", secretGob, len(secretGob))
|
||||||
secretJSON := input.ToJSON()
|
secretJSON := input.ToJSON()
|
||||||
fmt.Printf("secretJSON %#v %d\n", secretJSON, len(secretJSON))
|
log.Infof("secretJSON %#v %d\n", secretJSON, len(secretJSON))
|
||||||
secretFmt := input.MarshalFmt()
|
secretFmt := input.MarshalFmt()
|
||||||
fmt.Printf("secretFmt %#v %d\n", secretFmt, len(secretFmt))
|
log.Infof("secretFmt %#v %d\n", secretFmt, len(secretFmt))
|
||||||
|
|
||||||
output := testCredentials{APIToken: "refresh"}
|
output := testCredentials{APIToken: "refresh"}
|
||||||
require.NoError(t, output.UnmarshalStrings(secretStrings))
|
require.NoError(t, output.UnmarshalStrings(secretStrings))
|
||||||
fmt.Printf("strings out %#v \n", output)
|
log.Infof("strings out %#v \n", output)
|
||||||
require.True(t, input.IsSame(&output), "strings out not same")
|
require.True(t, input.IsSame(&output), "strings out not same")
|
||||||
|
|
||||||
output = testCredentials{APIToken: "refresh"}
|
output = testCredentials{APIToken: "refresh"}
|
||||||
require.NoError(t, output.UnmarshalGob(secretGob))
|
require.NoError(t, output.UnmarshalGob(secretGob))
|
||||||
fmt.Printf("gob out %#v\n \n", output)
|
log.Infof("gob out %#v\n \n", output)
|
||||||
assert.Equal(t, input, output)
|
assert.Equal(t, input, output)
|
||||||
|
|
||||||
output = testCredentials{APIToken: "refresh"}
|
output = testCredentials{APIToken: "refresh"}
|
||||||
require.NoError(t, output.FromJSON(secretJSON))
|
require.NoError(t, output.FromJSON(secretJSON))
|
||||||
fmt.Printf("json out %#v \n", output)
|
log.Infof("json out %#v \n", output)
|
||||||
require.True(t, input.IsSame(&output), "json out not same")
|
require.True(t, input.IsSame(&output), "json out not same")
|
||||||
|
|
||||||
/*
|
/*
|
||||||
// Simple Fscanf not working!
|
// Simple Fscanf not working!
|
||||||
output = testCredentials{APIToken: "refresh"}
|
output = testCredentials{APIToken: "refresh"}
|
||||||
require.NoError(t, output.UnmarshalFmt(secretFmt))
|
require.NoError(t, output.UnmarshalFmt(secretFmt))
|
||||||
fmt.Printf("fmt out %#v \n", output)
|
log.Infof("fmt out %#v \n", output)
|
||||||
require.True(t, input.IsSame(&output), "fmt out not same")
|
require.True(t, input.IsSame(&output), "fmt out not same")
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
@ -285,13 +285,13 @@ func TestMarshal(t *testing.T) {
|
|||||||
IsHidden: true,
|
IsHidden: true,
|
||||||
IsCombinedAddressMode: false,
|
IsCombinedAddressMode: false,
|
||||||
}
|
}
|
||||||
fmt.Printf("input %#v\n", input)
|
log.Infof("input %#v\n", input)
|
||||||
|
|
||||||
secret := input.Marshal()
|
secret := input.Marshal()
|
||||||
fmt.Printf("secret %#v %d\n", secret, len(secret))
|
log.Infof("secret %#v %d\n", secret, len(secret))
|
||||||
|
|
||||||
output := Credentials{APIToken: "refresh"}
|
output := Credentials{APIToken: "refresh"}
|
||||||
require.NoError(t, output.Unmarshal(secret))
|
require.NoError(t, output.Unmarshal(secret))
|
||||||
fmt.Printf("output %#v\n", output)
|
log.Infof("output %#v\n", output)
|
||||||
assert.Equal(t, input, output)
|
assert.Equal(t, input, output)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,7 +19,7 @@ package algo
|
|||||||
|
|
||||||
import "reflect"
|
import "reflect"
|
||||||
|
|
||||||
// SetIntersection complexity: O(n^2), could be better but this is simple enough
|
// SetIntersection complexity: O(n^2), could be better but this is simple enough.
|
||||||
func SetIntersection(a, b interface{}, eq func(a, b interface{}) bool) []interface{} {
|
func SetIntersection(a, b interface{}, eq func(a, b interface{}) bool) []interface{} {
|
||||||
set := make([]interface{}, 0)
|
set := make([]interface{}, 0)
|
||||||
av := reflect.ValueOf(a)
|
av := reflect.ValueOf(a)
|
||||||
|
|||||||
@ -51,9 +51,8 @@ func WriteAttachmentBody(w io.Writer, kr *crypto.KeyRing, m *pmapi.Message, att
|
|||||||
var dr io.Reader
|
var dr io.Reader
|
||||||
dr, err = att.Decrypt(r, kr)
|
dr, err = att.Decrypt(r, kr)
|
||||||
if err == openpgperrors.ErrKeyIncorrect {
|
if err == openpgperrors.ErrKeyIncorrect {
|
||||||
// Do not fail if attachment is encrypted with a different key.
|
err = nil //nolint[wastedassing] Do not fail if attachment is encrypted with a different key.
|
||||||
dr = r
|
dr = r
|
||||||
err = nil
|
|
||||||
att.Name += ".gpg"
|
att.Name += ".gpg"
|
||||||
att.MIMEType = "application/pgp-encrypted" //nolint
|
att.MIMEType = "application/pgp-encrypted" //nolint
|
||||||
} else if err != nil && err != openpgperrors.ErrSignatureExpired {
|
} else if err != nil && err != openpgperrors.ErrSignatureExpired {
|
||||||
|
|||||||
@ -48,7 +48,7 @@ func NewBuilder(client pmapi.Client, message *pmapi.Message) *Builder {
|
|||||||
return &Builder{cl: client, msg: message, EncryptedToHTML: true, successfullyDecrypted: false}
|
return &Builder{cl: client, msg: message, EncryptedToHTML: true, successfullyDecrypted: false}
|
||||||
}
|
}
|
||||||
|
|
||||||
// fetchMessage will update original PM message if successful
|
// fetchMessage will update original PM message if successful.
|
||||||
func (bld *Builder) fetchMessage() (err error) {
|
func (bld *Builder) fetchMessage() (err error) {
|
||||||
if bld.msg.Body != "" {
|
if bld.msg.Body != "" {
|
||||||
return nil
|
return nil
|
||||||
@ -211,11 +211,11 @@ func (bld *Builder) BuildMessage() (structure *BodyStructure, message []byte, er
|
|||||||
return structure, message, err
|
return structure, message, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// SuccessfullyDecrypted is true when message was fetched and decrypted successfully
|
// SuccessfullyDecrypted is true when message was fetched and decrypted successfully.
|
||||||
func (bld *Builder) SuccessfullyDecrypted() bool { return bld.successfullyDecrypted }
|
func (bld *Builder) SuccessfullyDecrypted() bool { return bld.successfullyDecrypted }
|
||||||
|
|
||||||
// WriteBody decrypts PM message and writes main body section. The external PGP
|
// WriteBody decrypts PM message and writes main body section. The external PGP
|
||||||
// message is written as is (including attachments)
|
// message is written as is (including attachments).
|
||||||
func (bld *Builder) WriteBody(w io.Writer) error {
|
func (bld *Builder) WriteBody(w io.Writer) error {
|
||||||
kr, err := bld.cl.KeyRingForAddressID(bld.msg.AddressID)
|
kr, err := bld.cl.KeyRingForAddressID(bld.msg.AddressID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -238,7 +238,7 @@ func (bld *Builder) WriteBody(w io.Writer) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// WriteAttachmentBody decrypts and writes the attachments
|
// WriteAttachmentBody decrypts and writes the attachments.
|
||||||
func (bld *Builder) WriteAttachmentBody(w io.Writer, att *pmapi.Attachment, attReader io.Reader) (err error) {
|
func (bld *Builder) WriteAttachmentBody(w io.Writer, att *pmapi.Attachment, attReader io.Reader) (err error) {
|
||||||
kr, err := bld.cl.KeyRingForAddressID(bld.msg.AddressID)
|
kr, err := bld.cl.KeyRingForAddressID(bld.msg.AddressID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -248,9 +248,8 @@ func (bld *Builder) WriteAttachmentBody(w io.Writer, att *pmapi.Attachment, attR
|
|||||||
var dr io.Reader
|
var dr io.Reader
|
||||||
dr, err = att.Decrypt(attReader, kr)
|
dr, err = att.Decrypt(attReader, kr)
|
||||||
if err == openpgperrors.ErrKeyIncorrect {
|
if err == openpgperrors.ErrKeyIncorrect {
|
||||||
// Do not fail if attachment is encrypted with a different key
|
err = nil //nolint[wastedasign] Do not fail if attachment is encrypted with a different key
|
||||||
dr = attReader
|
dr = attReader
|
||||||
err = nil
|
|
||||||
att.Name += ".gpg"
|
att.Name += ".gpg"
|
||||||
att.MIMEType = "application/pgp-encrypted"
|
att.MIMEType = "application/pgp-encrypted"
|
||||||
} else if err != nil && err != openpgperrors.ErrSignatureExpired {
|
} else if err != nil && err != openpgperrors.ErrSignatureExpired {
|
||||||
|
|||||||
@ -38,7 +38,7 @@ type SectionInfo struct {
|
|||||||
reader io.Reader
|
reader io.Reader
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read and count
|
// Read and count.
|
||||||
func (si *SectionInfo) Read(p []byte) (n int, err error) {
|
func (si *SectionInfo) Read(p []byte) (n int, err error) {
|
||||||
n, err = si.reader.Read(p)
|
n, err = si.reader.Read(p)
|
||||||
si.Size += n
|
si.Size += n
|
||||||
@ -237,11 +237,11 @@ func (bs *BodyStructure) parseAllChildSections(r io.Reader, currentPath []int, s
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Clear all buffers.
|
// Clear all buffers.
|
||||||
bodyReader = nil
|
bodyReader = nil //nolint[wastedassign] just to be sure we clear garbage collector
|
||||||
bodyInfo.reader = nil
|
bodyInfo.reader = nil
|
||||||
tp.R = nil
|
tp.R = nil
|
||||||
tp = nil
|
tp = nil //nolint[wastedassign] just to be sure we clear garbage collector
|
||||||
bufInfo = nil // nolint
|
bufInfo = nil //nolint[ineffassign] just to be sure we clear garbage collector
|
||||||
info.reader = nil
|
info.reader = nil
|
||||||
|
|
||||||
// Store boundaries.
|
// Store boundaries.
|
||||||
@ -305,6 +305,11 @@ func stringPathFromInts(ints []int) (ret string) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (bs *BodyStructure) hasInfo(sectionPath []int) bool {
|
||||||
|
_, err := bs.getInfo(sectionPath)
|
||||||
|
return err == nil
|
||||||
|
}
|
||||||
|
|
||||||
func (bs *BodyStructure) getInfo(sectionPath []int) (sectionInfo *SectionInfo, err error) {
|
func (bs *BodyStructure) getInfo(sectionPath []int) (sectionInfo *SectionInfo, err error) {
|
||||||
path := stringPathFromInts(sectionPath)
|
path := stringPathFromInts(sectionPath)
|
||||||
sectionInfo, ok := (*bs)[path]
|
sectionInfo, ok := (*bs)[path]
|
||||||
@ -404,7 +409,7 @@ func (bs *BodyStructure) IMAPBodyStructure(currentPart []int) (imapBS *imap.Body
|
|||||||
|
|
||||||
nextPart := append(currentPart, 1)
|
nextPart := append(currentPart, 1)
|
||||||
for {
|
for {
|
||||||
if _, err := bs.getInfo(nextPart); err != nil {
|
if !bs.hasInfo(nextPart) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
var subStruct *imap.BodyStructure
|
var subStruct *imap.BodyStructure
|
||||||
|
|||||||
@ -89,7 +89,7 @@ func TestParallelErrorInProcess(t *testing.T) {
|
|||||||
return value, nil
|
return value, nil
|
||||||
}
|
}
|
||||||
collect := func(idx int, value interface{}) error {
|
collect := func(idx int, value interface{}) error {
|
||||||
lastCollected = value.(int)
|
lastCollected = value.(int) //nolint[forcetypeassert]
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -61,7 +61,7 @@ func NewBasicTLSDialer() *BasicTLSDialer {
|
|||||||
func (b *BasicTLSDialer) DialTLS(network, address string) (conn net.Conn, err error) {
|
func (b *BasicTLSDialer) DialTLS(network, address string) (conn net.Conn, err error) {
|
||||||
dialer := &net.Dialer{Timeout: 30 * time.Second} // Alternative Routes spec says this should be a 30s timeout.
|
dialer := &net.Dialer{Timeout: 30 * time.Second} // Alternative Routes spec says this should be a 30s timeout.
|
||||||
|
|
||||||
var tlsConfig *tls.Config = nil
|
var tlsConfig *tls.Config
|
||||||
|
|
||||||
// If we are not dialing the standard API then we should skip cert verification checks.
|
// If we are not dialing the standard API then we should skip cert verification checks.
|
||||||
if address != rootURL {
|
if address != rootURL {
|
||||||
|
|||||||
@ -39,7 +39,7 @@ func NewProxyTLSDialer(dialer TLSDialer, cm *ClientManager) *ProxyTLSDialer {
|
|||||||
// DialTLS dials the given network/address. If it fails, it retries using a proxy.
|
// DialTLS dials the given network/address. If it fails, it retries using a proxy.
|
||||||
func (d *ProxyTLSDialer) DialTLS(network, address string) (conn net.Conn, err error) {
|
func (d *ProxyTLSDialer) DialTLS(network, address string) (conn net.Conn, err error) {
|
||||||
if conn, err = d.dialer.DialTLS(network, address); err == nil {
|
if conn, err = d.dialer.DialTLS(network, address); err == nil {
|
||||||
return
|
return conn, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if !d.cm.allowProxy {
|
if !d.cm.allowProxy {
|
||||||
|
|||||||
@ -107,6 +107,8 @@ func (em *EventMessage) UnmarshalJSON(b []byte) (err error) {
|
|||||||
case EventUpdate, EventUpdateFlags:
|
case EventUpdate, EventUpdateFlags:
|
||||||
em.Updated = &EventMessageUpdated{ID: raw.ID}
|
em.Updated = &EventMessageUpdated{ID: raw.ID}
|
||||||
return json.Unmarshal(raw.Message, em.Updated)
|
return json.Unmarshal(raw.Message, em.Updated)
|
||||||
|
case EventDelete:
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -121,6 +123,7 @@ func (em *EventMessage) MarshalJSON() ([]byte, error) {
|
|||||||
raw.Message, err = json.Marshal(em.Created)
|
raw.Message, err = json.Marshal(em.Created)
|
||||||
case EventUpdate, EventUpdateFlags:
|
case EventUpdate, EventUpdateFlags:
|
||||||
raw.Message, err = json.Marshal(em.Updated)
|
raw.Message, err = json.Marshal(em.Updated)
|
||||||
|
case EventDelete:
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@ -25,7 +25,7 @@ import (
|
|||||||
"github.com/ProtonMail/gopenpgp/v2/crypto"
|
"github.com/ProtonMail/gopenpgp/v2/crypto"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Flags
|
// Key flags.
|
||||||
const (
|
const (
|
||||||
UseToVerifyFlag = 1 << iota
|
UseToVerifyFlag = 1 << iota
|
||||||
UseToEncryptFlag
|
UseToEncryptFlag
|
||||||
|
|||||||
@ -22,7 +22,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
)
|
)
|
||||||
|
|
||||||
// System labels
|
// System labels.
|
||||||
const (
|
const (
|
||||||
InboxLabel = "0"
|
InboxLabel = "0"
|
||||||
AllDraftsLabel = "1"
|
AllDraftsLabel = "1"
|
||||||
@ -188,7 +188,7 @@ func (c *client) DeleteLabel(id string) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// LeastUsedColor is intended to return color for creating a new inbox or label
|
// LeastUsedColor is intended to return color for creating a new inbox or label.
|
||||||
func LeastUsedColor(colors []string) (color string) {
|
func LeastUsedColor(colors []string) (color string) {
|
||||||
color = LabelColors[0]
|
color = LabelColors[0]
|
||||||
frequency := map[string]int{}
|
frequency := map[string]int{}
|
||||||
|
|||||||
@ -24,14 +24,14 @@ import (
|
|||||||
"github.com/ProtonMail/gopenpgp/v2/crypto"
|
"github.com/ProtonMail/gopenpgp/v2/crypto"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Draft actions
|
// Draft actions.
|
||||||
const (
|
const (
|
||||||
DraftActionReply = 0
|
DraftActionReply = 0
|
||||||
DraftActionReplyAll = 1
|
DraftActionReplyAll = 1
|
||||||
DraftActionForward = 2
|
DraftActionForward = 2
|
||||||
)
|
)
|
||||||
|
|
||||||
// PackageFlag for send message package types
|
// PackageFlag for send message package types.
|
||||||
type PackageFlag int
|
type PackageFlag int
|
||||||
|
|
||||||
func (p *PackageFlag) Has(flag PackageFlag) bool { return iHasFlag(int(*p), int(flag)) }
|
func (p *PackageFlag) Has(flag PackageFlag) bool { return iHasFlag(int(*p), int(flag)) }
|
||||||
@ -65,7 +65,7 @@ const (
|
|||||||
SignatureAttachedArmored = SignatureFlag(2)
|
SignatureAttachedArmored = SignatureFlag(2)
|
||||||
)
|
)
|
||||||
|
|
||||||
// DraftReq defines paylod for creating drafts
|
// DraftReq defines paylod for creating drafts.
|
||||||
type DraftReq struct {
|
type DraftReq struct {
|
||||||
Message *Message
|
Message *Message
|
||||||
ParentID string `json:",omitempty"`
|
ParentID string `json:",omitempty"`
|
||||||
|
|||||||
@ -52,7 +52,7 @@ func getTrustedServerWithHandler(handler http.HandlerFunc) *httptest.Server {
|
|||||||
return proxy
|
return proxy
|
||||||
}
|
}
|
||||||
|
|
||||||
// server.crt
|
// server.crt data.
|
||||||
const servercrt = `
|
const servercrt = `
|
||||||
-----BEGIN CERTIFICATE-----
|
-----BEGIN CERTIFICATE-----
|
||||||
MIIE5TCCA82gAwIBAgIJAKsmhcMFGfGcMA0GCSqGSIb3DQEBCwUAMIGsMQswCQYD
|
MIIE5TCCA82gAwIBAgIJAKsmhcMFGfGcMA0GCSqGSIb3DQEBCwUAMIGsMQswCQYD
|
||||||
|
|||||||
@ -172,11 +172,11 @@ func checkHeader(h http.Header, field, exp string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func isAuthReq(r *http.Request, uid, token string) error { // nolint[unparam]
|
func isAuthReq(r *http.Request, uid, token string) error { //nolint[unparam] always retrieves testUID
|
||||||
if err := checkHeader(r.Header, "x-pm-uid", uid); err != nil {
|
if err := checkHeader(r.Header, "x-pm-uid", uid); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := checkHeader(r.Header, "authorization", "Bearer "+token); err != nil {
|
if err := checkHeader(r.Header, "authorization", "Bearer "+token); err != nil { //nolint[revive] can return the error right away but this is easier to read
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@ -33,7 +33,7 @@ import (
|
|||||||
var ErrTLSMismatch = errors.New("no TLS fingerprint match found")
|
var ErrTLSMismatch = errors.New("no TLS fingerprint match found")
|
||||||
|
|
||||||
// TrustedAPIPins contains trusted public keys of the protonmail API and proxies.
|
// TrustedAPIPins contains trusted public keys of the protonmail API and proxies.
|
||||||
// NOTE: the proxy pins are the same for all proxy servers, guaranteed by infra team ;)
|
// NOTE: the proxy pins are the same for all proxy servers, guaranteed by infra team ;).
|
||||||
var TrustedAPIPins = []string{ // nolint[gochecknoglobals]
|
var TrustedAPIPins = []string{ // nolint[gochecknoglobals]
|
||||||
// api.protonmail.ch
|
// api.protonmail.ch
|
||||||
`pin-sha256="drtmcR2kFkM8qJClsuWgUzxgBkePfRCkRpqUesyDmeE="`, // current
|
`pin-sha256="drtmcR2kFkM8qJClsuWgUzxgBkePfRCkRpqUesyDmeE="`, // current
|
||||||
|
|||||||
@ -29,7 +29,7 @@ const (
|
|||||||
PaidAdminRole
|
PaidAdminRole
|
||||||
)
|
)
|
||||||
|
|
||||||
// User status
|
// User status.
|
||||||
const (
|
const (
|
||||||
DeletedUser = 0
|
DeletedUser = 0
|
||||||
DisabledUser = 1
|
DisabledUser = 1
|
||||||
|
|||||||
@ -29,12 +29,12 @@ import (
|
|||||||
"github.com/jameskeane/bcrypt"
|
"github.com/jameskeane/bcrypt"
|
||||||
)
|
)
|
||||||
|
|
||||||
// BCryptHash function bcrypt algorithm to hash password with salt
|
// BCryptHash function bcrypt algorithm to hash password with salt.
|
||||||
func BCryptHash(password string, salt string) (string, error) {
|
func BCryptHash(password string, salt string) (string, error) {
|
||||||
return bcrypt.Hash(password, salt)
|
return bcrypt.Hash(password, salt)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExpandHash extends the byte data for SRP flow
|
// ExpandHash extends the byte data for SRP flow.
|
||||||
func ExpandHash(data []byte) []byte {
|
func ExpandHash(data []byte) []byte {
|
||||||
part0 := sha512.Sum512(append(data, 0))
|
part0 := sha512.Sum512(append(data, 0))
|
||||||
part1 := sha512.Sum512(append(data, 1))
|
part1 := sha512.Sum512(append(data, 1))
|
||||||
@ -51,7 +51,7 @@ func ExpandHash(data []byte) []byte {
|
|||||||
// HashPassword returns the hash of password argument. Based on version number
|
// HashPassword returns the hash of password argument. Based on version number
|
||||||
// following arguments are used in addition to password:
|
// following arguments are used in addition to password:
|
||||||
// * 0, 1, 2: userName and modulus
|
// * 0, 1, 2: userName and modulus
|
||||||
// * 3, 4: salt and modulus
|
// * 3, 4: salt and modulus.
|
||||||
func HashPassword(authVersion int, password, userName string, salt, modulus []byte) ([]byte, error) {
|
func HashPassword(authVersion int, password, userName string, salt, modulus []byte) ([]byte, error) {
|
||||||
switch authVersion {
|
switch authVersion {
|
||||||
case 4, 3:
|
case 4, 3:
|
||||||
|
|||||||
@ -37,7 +37,7 @@ var (
|
|||||||
|
|
||||||
// Store random reader in a variable to be able to overwrite it in tests
|
// Store random reader in a variable to be able to overwrite it in tests
|
||||||
|
|
||||||
// Amored pubkey for modulus verification
|
// Amored pubkey for modulus verification.
|
||||||
const modulusPubkey = `-----BEGIN PGP PUBLIC KEY BLOCK-----
|
const modulusPubkey = `-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||||
|
|
||||||
xjMEXAHLgxYJKwYBBAHaRw8BAQdAFurWXXwjTemqjD7CXjXVyKf0of7n9Ctm
|
xjMEXAHLgxYJKwYBBAHaRw8BAQdAFurWXXwjTemqjD7CXjXVyKf0of7n9Ctm
|
||||||
@ -73,12 +73,12 @@ func ReadClearSignedMessage(signedMessage string) (string, error) {
|
|||||||
return string(modulusBlock.Bytes), nil
|
return string(modulusBlock.Bytes), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// SrpProofs object
|
// SrpProofs object.
|
||||||
type SrpProofs struct { //nolint[golint]
|
type SrpProofs struct { //nolint[golint]
|
||||||
ClientProof, ClientEphemeral, ExpectedServerProof []byte
|
ClientProof, ClientEphemeral, ExpectedServerProof []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
// SrpAuth stores byte data for the calculation of SRP proofs
|
// SrpAuth stores byte data for the calculation of SRP proofs.
|
||||||
type SrpAuth struct { //nolint[golint]
|
type SrpAuth struct { //nolint[golint]
|
||||||
Modulus, ServerEphemeral, HashedPassword []byte
|
Modulus, ServerEphemeral, HashedPassword []byte
|
||||||
}
|
}
|
||||||
@ -213,7 +213,7 @@ func (s *SrpAuth) GenerateSrpProofs(length int) (res *SrpProofs, err error) { //
|
|||||||
return &SrpProofs{ClientEphemeral: fromInt(clientEphemeral), ClientProof: clientProof, ExpectedServerProof: serverProof}, nil
|
return &SrpProofs{ClientEphemeral: fromInt(clientEphemeral), ClientProof: clientProof, ExpectedServerProof: serverProof}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GenerateVerifier verifier for update pwds and create accounts
|
// GenerateVerifier verifier for update pwds and create accounts.
|
||||||
func (s *SrpAuth) GenerateVerifier(length int) ([]byte, error) {
|
func (s *SrpAuth) GenerateVerifier(length int) ([]byte, error) {
|
||||||
return nil, errors.New("pm-srp: the client doesn't need SRP GenerateVerifier")
|
return nil, errors.New("pm-srp: the client doesn't need SRP GenerateVerifier")
|
||||||
}
|
}
|
||||||
|
|||||||
@ -28,10 +28,10 @@ import (
|
|||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
// maxFileSize limit tre single file size after decopression is not larger than 1GB
|
// maxFileSize limit tre single file size after decopression is not larger than 1GB.
|
||||||
const maxFileSize = int64(1 * 1024 * 1024 * 1024) // 1 GB
|
const maxFileSize = int64(1 * 1024 * 1024 * 1024) // 1 GB
|
||||||
|
|
||||||
// ErrFileTooLarge returned when decompressed file is too large
|
// ErrFileTooLarge returned when decompressed file is too large.
|
||||||
var ErrFileTooLarge = errors.New("trying to decompress file larger than 1GB")
|
var ErrFileTooLarge = errors.New("trying to decompress file larger than 1GB")
|
||||||
|
|
||||||
type limitReader struct {
|
type limitReader struct {
|
||||||
@ -40,6 +40,7 @@ type limitReader struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Read returns error if limit was exceeded. Inspired by io.LimitReader.Read
|
// Read returns error if limit was exceeded. Inspired by io.LimitReader.Read
|
||||||
|
// implementation.
|
||||||
func (lr *limitReader) Read(p []byte) (n int, err error) {
|
func (lr *limitReader) Read(p []byte) (n int, err error) {
|
||||||
if lr.n <= 0 {
|
if lr.n <= 0 {
|
||||||
return 0, ErrFileTooLarge
|
return 0, ErrFileTooLarge
|
||||||
@ -52,7 +53,7 @@ func (lr *limitReader) Read(p []byte) (n int, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// UntarToDir decopmress and unarchive the files into directory
|
// UntarToDir decopmress and unarchive the files into directory.
|
||||||
func UntarToDir(r io.Reader, dir string) error {
|
func UntarToDir(r io.Reader, dir string) error {
|
||||||
tr := tar.NewReader(r)
|
tr := tar.NewReader(r)
|
||||||
|
|
||||||
|
|||||||
@ -132,8 +132,8 @@ func BenchmarkIMAPAppleMail(b *testing.B) {
|
|||||||
`)])`,
|
`)])`,
|
||||||
`UID FETCH ` + newUID + ` (BODYSTRUCTURE BODY.PEEK[HEADER])`,
|
`UID FETCH ` + newUID + ` (BODYSTRUCTURE BODY.PEEK[HEADER])`,
|
||||||
// if email has attachment it is splitted to several fetches
|
// if email has attachment it is splitted to several fetches
|
||||||
//`UID FETCH 133 (BODY.PEEK[3]<0.5877469> BODY.PEEK[1] BODY.PEEK[2])`,
|
// `UID FETCH 133 (BODY.PEEK[3]<0.5877469> BODY.PEEK[1] BODY.PEEK[2])`,
|
||||||
//`UID FETCH 133 BODY.PEEK[3]<5877469.2925661>`,
|
// `UID FETCH 133 BODY.PEEK[3]<5877469.2925661>`,
|
||||||
// here I will just use section download, which is used by AppleMail
|
// here I will just use section download, which is used by AppleMail
|
||||||
`UID FETCH ` + newUID + ` BODY.PEEK[1]`,
|
`UID FETCH ` + newUID + ` BODY.PEEK[1]`,
|
||||||
// here I will just use partial download, which is used by AppleMail
|
// here I will just use partial download, which is used by AppleMail
|
||||||
|
|||||||
@ -43,8 +43,8 @@ func newFakeSettings() *fakeSettings {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// We should use nonstandard ports to not conflict with bridge.
|
// We should use nonstandard ports to not conflict with bridge.
|
||||||
s.SetInt(settings.IMAPPortKey, 21100+rand.Intn(100)) //noling[gosec] G404 It is OK to use weak random number generator here
|
s.SetInt(settings.IMAPPortKey, 21100+rand.Intn(100)) //nolint[gosec] G404 It is OK to use weak random number generator here
|
||||||
s.SetInt(settings.SMTPPortKey, 21200+rand.Intn(100)) //noling[gosec] G404 It is OK to use weak random number generator here
|
s.SetInt(settings.SMTPPortKey, 21200+rand.Intn(100)) //nolint[gosec] G404 It is OK to use weak random number generator here
|
||||||
|
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|||||||
@ -88,7 +88,7 @@ func (ctx *TestContext) GetTransferRemoteIMAPServer() *mocks.IMAPServer {
|
|||||||
return ctx.transferRemoteIMAPServer
|
return ctx.transferRemoteIMAPServer
|
||||||
}
|
}
|
||||||
|
|
||||||
port := 21300 + rand.Intn(100)
|
port := 21300 + rand.Intn(100) //nolint[gosec] It is OK to use weaker rand generator here
|
||||||
ctx.transferRemoteIMAPServer = mocks.NewIMAPServer("user", "pass", "127.0.0.1", strconv.Itoa(port))
|
ctx.transferRemoteIMAPServer = mocks.NewIMAPServer("user", "pass", "127.0.0.1", strconv.Itoa(port))
|
||||||
|
|
||||||
ctx.transferRemoteIMAPServer.Start()
|
ctx.transferRemoteIMAPServer.Start()
|
||||||
|
|||||||
@ -37,7 +37,7 @@ func (ctx *TestContext) GetUsers() *users.Users {
|
|||||||
|
|
||||||
// LoginUser logs in the user with the given username, password, and mailbox password.
|
// LoginUser logs in the user with the given username, password, and mailbox password.
|
||||||
func (ctx *TestContext) LoginUser(username, password, mailboxPassword string) (err error) {
|
func (ctx *TestContext) LoginUser(username, password, mailboxPassword string) (err error) {
|
||||||
srp.RandReader = rand.New(rand.NewSource(42))
|
srp.RandReader = rand.New(rand.NewSource(42)) //nolint[gosec] It is OK to use weaker random number generator here
|
||||||
|
|
||||||
client, auth, err := ctx.users.Login(username, password)
|
client, auth, err := ctx.users.Login(username, password)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -120,7 +120,7 @@ func (ctx *TestContext) eventuallySyncIsFinished(store *store.Store) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// EventuallySyncIsFinishedForUsername will wait until sync is finished or
|
// EventuallySyncIsFinishedForUsername will wait until sync is finished or
|
||||||
// deadline is reached see eventuallySyncIsFinished for timing
|
// deadline is reached see eventuallySyncIsFinished for timing.
|
||||||
func (ctx *TestContext) EventuallySyncIsFinishedForUsername(username string) {
|
func (ctx *TestContext) EventuallySyncIsFinishedForUsername(username string) {
|
||||||
store, err := ctx.GetStore(username)
|
store, err := ctx.GetStore(username)
|
||||||
assert.Nil(ctx.t, err)
|
assert.Nil(ctx.t, err)
|
||||||
|
|||||||
@ -47,8 +47,5 @@ func (api *FakePMAPI) CreateAttachment(attachment *pmapi.Attachment, data io.Rea
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (api *FakePMAPI) DeleteAttachment(attID string) error {
|
func (api *FakePMAPI) DeleteAttachment(attID string) error {
|
||||||
if err := api.checkAndRecordCall(DELETE, "/mail/v4/attachments/"+attID, nil); err != nil {
|
return api.checkAndRecordCall(DELETE, "/mail/v4/attachments/"+attID, nil)
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -108,7 +108,7 @@ func thereIsNoDatabaseFileForUser(bddUserID string) error {
|
|||||||
}
|
}
|
||||||
filePath := ctx.GetDatabaseFilePath(account.UserID())
|
filePath := ctx.GetDatabaseFilePath(account.UserID())
|
||||||
if _, err := os.Stat(filePath); err != nil {
|
if _, err := os.Stat(filePath); err != nil {
|
||||||
return nil
|
return nil //nolint[nilerr] Error means the file is not there or not accessible so test passed
|
||||||
}
|
}
|
||||||
return internalError(os.Remove(filePath), "removing database file of %s", account.Username())
|
return internalError(os.Remove(filePath), "removing database file of %s", account.Username())
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user