From 78eaed64d5b2fb33cd626bf364f561bd729aa371 Mon Sep 17 00:00:00 2001 From: Jan-Lukas Else Date: Sun, 12 Apr 2020 12:34:51 +0200 Subject: [PATCH] Use pointers --- config.go | 11 ++++++----- config_test.go | 26 +++++++++++++------------- forms.go | 27 ++++++++++++++------------- forms_test.go | 20 ++++++++++---------- mail.go | 32 ++++++++++++++++---------------- mail_test.go | 28 ++++++++++++++-------------- mailygo.go | 2 +- spamcheck.go | 19 ++++++++++--------- spamcheck_test.go | 4 ++-- 9 files changed, 86 insertions(+), 83 deletions(-) diff --git a/config.go b/config.go index 4c7bb05..98f6b59 100644 --- a/config.go +++ b/config.go @@ -2,6 +2,7 @@ package main import ( "errors" + "github.com/caarlos0/env/v6" ) @@ -19,15 +20,15 @@ type config struct { Blacklist []string `env:"BLACKLIST" envSeparator:"," envDefault:"gambling,casino"` } -func parseConfig() (config, error) { - cfg := config{} - if err := env.Parse(&cfg); err != nil { +func parseConfig() (*config, error) { + cfg := &config{} + if err := env.Parse(cfg); err != nil { return cfg, errors.New("failed to parse config") } return cfg, nil } -func checkRequiredConfig(cfg config) bool { +func checkRequiredConfig(cfg *config) bool { if cfg.DefaultRecipient == "" { return false } @@ -47,4 +48,4 @@ func checkRequiredConfig(cfg config) bool { return false } return true -} \ No newline at end of file +} diff --git a/config_test.go b/config_test.go index 083b78e..b4681ae 100644 --- a/config_test.go +++ b/config_test.go @@ -90,7 +90,7 @@ func Test_parseConfig(t *testing.T) { } func Test_checkRequiredConfig(t *testing.T) { - validConfig := config{ + validConfig := &config{ Port: 8080, HoneyPots: []string{"_t_email"}, DefaultRecipient: "mail@example.com", @@ -107,44 +107,44 @@ func Test_checkRequiredConfig(t *testing.T) { } }) t.Run("Default recipient missing", func(t *testing.T) { - newConfig := validConfig + newConfig := *validConfig newConfig.DefaultRecipient = "" - if false != checkRequiredConfig(newConfig) { + if false != checkRequiredConfig(&newConfig) { t.Error() } }) t.Run("Allowed recipients missing", func(t *testing.T) { - newConfig := validConfig + newConfig := *validConfig newConfig.AllowedRecipients = nil - if false != checkRequiredConfig(newConfig) { + if false != checkRequiredConfig(&newConfig) { t.Error() } }) t.Run("Sender missing", func(t *testing.T) { - newConfig := validConfig + newConfig := *validConfig newConfig.Sender = "" - if false != checkRequiredConfig(newConfig) { + if false != checkRequiredConfig(&newConfig) { t.Error() } }) t.Run("SMTP user missing", func(t *testing.T) { - newConfig := validConfig + newConfig := *validConfig newConfig.SmtpUser = "" - if false != checkRequiredConfig(newConfig) { + if false != checkRequiredConfig(&newConfig) { t.Error() } }) t.Run("SMTP password missing", func(t *testing.T) { - newConfig := validConfig + newConfig := *validConfig newConfig.SmtpPassword = "" - if false != checkRequiredConfig(newConfig) { + if false != checkRequiredConfig(&newConfig) { t.Error() } }) t.Run("SMTP host missing", func(t *testing.T) { - newConfig := validConfig + newConfig := *validConfig newConfig.SmtpHost = "" - if false != checkRequiredConfig(newConfig) { + if false != checkRequiredConfig(&newConfig) { t.Error() } }) diff --git a/forms.go b/forms.go index 4387ac8..f05ebd7 100644 --- a/forms.go +++ b/forms.go @@ -1,10 +1,11 @@ package main import ( - "github.com/microcosm-cc/bluemonday" "html" "net/http" "net/url" + + "github.com/microcosm-cc/bluemonday" ) type FormValues map[string][]string @@ -20,7 +21,7 @@ func FormHandler(w http.ResponseWriter, r *http.Request) { return } _ = r.ParseForm() - sanitizedForm := sanitizeForm(r.PostForm) + sanitizedForm := sanitizeForm(&r.PostForm) go func() { if !isBot(sanitizedForm) { sendForm(sanitizedForm) @@ -30,23 +31,23 @@ func FormHandler(w http.ResponseWriter, r *http.Request) { return } -func sanitizeForm(values url.Values) FormValues { +func sanitizeForm(values *url.Values) *FormValues { p := bluemonday.StrictPolicy() sanitizedForm := make(FormValues) - for key, values := range values { + for key, values := range *values { var sanitizedValues []string for _, value := range values { sanitizedValues = append(sanitizedValues, html.UnescapeString(p.Sanitize(value))) } sanitizedForm[html.UnescapeString(p.Sanitize(key))] = sanitizedValues } - return sanitizedForm + return &sanitizedForm } -func isBot(values FormValues) bool { +func isBot(values *FormValues) bool { for _, honeyPot := range appConfig.HoneyPots { - if len(values[honeyPot]) > 0 { - for _, value := range values[honeyPot] { + if len((*values)[honeyPot]) > 0 { + for _, value := range (*values)[honeyPot] { if value != "" { return true } @@ -56,15 +57,15 @@ func isBot(values FormValues) bool { return checkValues(values) } -func sendResponse(values FormValues, w http.ResponseWriter) { - if len(values["_redirectTo"]) == 1 && values["_redirectTo"][0] != "" { - w.Header().Add("Location", values["_redirectTo"][0]) +func sendResponse(values *FormValues, w http.ResponseWriter) { + if len((*values)["_redirectTo"]) == 1 && (*values)["_redirectTo"][0] != "" { + w.Header().Add("Location", (*values)["_redirectTo"][0]) w.WriteHeader(http.StatusSeeOther) - _, _ = w.Write([]byte("Go to " + values["_redirectTo"][0])) + _, _ = w.Write([]byte("Go to " + (*values)["_redirectTo"][0])) return } else { w.WriteHeader(http.StatusCreated) _, _ = w.Write([]byte("Submitted form")) return } -} \ No newline at end of file +} diff --git a/forms_test.go b/forms_test.go index 4bd0729..ff47510 100644 --- a/forms_test.go +++ b/forms_test.go @@ -11,9 +11,9 @@ import ( func Test_sanitizeForm(t *testing.T) { t.Run("Sanitize form", func(t *testing.T) { - result := sanitizeForm(url.Values{"Test": {"Test"}}) + result := sanitizeForm(&url.Values{"Test": {"Test"}}) want := FormValues{"Test": {"Test"}} - if !reflect.DeepEqual(result, want) { + if !reflect.DeepEqual(*result, want) { t.Error() } }) @@ -52,21 +52,21 @@ func TestFormHandler(t *testing.T) { func Test_isBot(t *testing.T) { t.Run("No bot", func(t *testing.T) { os.Clearenv() - result := isBot(FormValues{"_t_email": {""}}) + result := isBot(&FormValues{"_t_email": {""}}) if !reflect.DeepEqual(result, false) { t.Error() } }) t.Run("No honeypot", func(t *testing.T) { os.Clearenv() - result := isBot(FormValues{}) + result := isBot(&FormValues{}) if !reflect.DeepEqual(result, false) { t.Error() } }) t.Run("Bot", func(t *testing.T) { os.Clearenv() - result := isBot(FormValues{"_t_email": {"Test", ""}}) + result := isBot(&FormValues{"_t_email": {"Test", ""}}) if !reflect.DeepEqual(result, true) { t.Error() } @@ -75,7 +75,7 @@ func Test_isBot(t *testing.T) { func Test_sendResponse(t *testing.T) { t.Run("No redirect", func(t *testing.T) { - values := FormValues{} + values := &FormValues{} w := httptest.NewRecorder() sendResponse(values, w) if w.Code != http.StatusCreated { @@ -83,7 +83,7 @@ func Test_sendResponse(t *testing.T) { } }) t.Run("No redirect 2", func(t *testing.T) { - values := FormValues{ + values := &FormValues{ "_redirectTo": {""}, } w := httptest.NewRecorder() @@ -93,7 +93,7 @@ func Test_sendResponse(t *testing.T) { } }) t.Run("No redirect 3", func(t *testing.T) { - values := FormValues{ + values := &FormValues{ "_redirectTo": {"abc", "def"}, } w := httptest.NewRecorder() @@ -103,7 +103,7 @@ func Test_sendResponse(t *testing.T) { } }) t.Run("Redirect", func(t *testing.T) { - values := FormValues{ + values := &FormValues{ "_redirectTo": {"https://example.com"}, } w := httptest.NewRecorder() @@ -115,4 +115,4 @@ func Test_sendResponse(t *testing.T) { t.Error() } }) -} \ No newline at end of file +} diff --git a/mail.go b/mail.go index 41fc1fb..a6580bb 100644 --- a/mail.go +++ b/mail.go @@ -10,12 +10,12 @@ import ( "time" ) -func sendForm(values FormValues) { +func sendForm(values *FormValues) { recipient := findRecipient(values) sendMail(recipient, buildMessage(recipient, time.Now(), values)) } -func buildMessage(recipient string, date time.Time, values FormValues) string { +func buildMessage(recipient string, date time.Time, values *FormValues) string { var msgBuffer bytes.Buffer _, _ = fmt.Fprintf(&msgBuffer, "From: Forms <%s>", appConfig.Sender) _, _ = fmt.Fprintln(&msgBuffer) @@ -32,14 +32,14 @@ func buildMessage(recipient string, date time.Time, values FormValues) string { _, _ = fmt.Fprintln(&msgBuffer) bodyValues := removeMetaValues(values) var keys []string - for key, _ := range bodyValues { + for key := range *bodyValues { keys = append(keys, key) } sort.Strings(keys) for _, key := range keys { _, _ = fmt.Fprint(&msgBuffer, key) _, _ = fmt.Fprint(&msgBuffer, ": ") - _, _ = fmt.Fprintln(&msgBuffer, strings.Join(bodyValues[key], ", ")) + _, _ = fmt.Fprintln(&msgBuffer, strings.Join((*bodyValues)[key], ", ")) } return msgBuffer.String() } @@ -52,9 +52,9 @@ func sendMail(to, message string) { } } -func findRecipient(values FormValues) string { - if len(values["_to"]) == 1 && values["_to"][0] != "" { - formDefinedRecipient := values["_to"][0] +func findRecipient(values *FormValues) string { + if len((*values)["_to"]) == 1 && (*values)["_to"][0] != "" { + formDefinedRecipient := (*values)["_to"][0] for _, allowed := range appConfig.AllowedRecipients { if formDefinedRecipient == allowed { return formDefinedRecipient @@ -64,26 +64,26 @@ func findRecipient(values FormValues) string { return appConfig.DefaultRecipient } -func findFormName(values FormValues) string { - if len(values["_formName"]) == 1 && values["_formName"][0] != "" { - return values["_formName"][0] +func findFormName(values *FormValues) string { + if len((*values)["_formName"]) == 1 && (*values)["_formName"][0] != "" { + return (*values)["_formName"][0] } return "a form" } -func findReplyTo(values FormValues) string { - if len(values["_replyTo"]) == 1 && values["_replyTo"][0] != "" { - return values["_replyTo"][0] +func findReplyTo(values *FormValues) string { + if len((*values)["_replyTo"]) == 1 && (*values)["_replyTo"][0] != "" { + return (*values)["_replyTo"][0] } return "" } -func removeMetaValues(values FormValues) FormValues { +func removeMetaValues(values *FormValues) *FormValues { cleanedValues := FormValues{} - for key, value := range values { + for key, value := range *values { if !strings.HasPrefix(key, "_") { cleanedValues[key] = value } } - return cleanedValues + return &cleanedValues } diff --git a/mail_test.go b/mail_test.go index c731a84..225f4cf 100644 --- a/mail_test.go +++ b/mail_test.go @@ -17,7 +17,7 @@ func Test_findRecipient(t *testing.T) { } t.Run("No recipient specified", func(t *testing.T) { prepare() - values := FormValues{} + values := &FormValues{} result := findRecipient(values) if result != "mail@example.com" { t.Error() @@ -25,7 +25,7 @@ func Test_findRecipient(t *testing.T) { }) t.Run("Multiple recipients specified", func(t *testing.T) { prepare() - values := FormValues{ + values := &FormValues{ "_to": {"abc@example.com", "def@example.com"}, } result := findRecipient(values) @@ -35,7 +35,7 @@ func Test_findRecipient(t *testing.T) { }) t.Run("Allowed recipient specified", func(t *testing.T) { prepare() - values := FormValues{ + values := &FormValues{ "_to": {"test@example.com"}, } result := findRecipient(values) @@ -45,7 +45,7 @@ func Test_findRecipient(t *testing.T) { }) t.Run("Forbidden recipient specified", func(t *testing.T) { prepare() - values := FormValues{ + values := &FormValues{ "_to": {"forbidden@example.com"}, } result := findRecipient(values) @@ -57,17 +57,17 @@ func Test_findRecipient(t *testing.T) { func Test_findFormName(t *testing.T) { t.Run("No form name", func(t *testing.T) { - if "a form" != findFormName(FormValues{}) { + if "a form" != findFormName(&FormValues{}) { t.Error() } }) t.Run("Multiple form names", func(t *testing.T) { - if "a form" != findFormName(FormValues{"_formName": {"Test", "ABC"}}) { + if "a form" != findFormName(&FormValues{"_formName": {"Test", "ABC"}}) { t.Error() } }) t.Run("Form name", func(t *testing.T) { - if "Test" != findFormName(FormValues{"_formName": {"Test"}}) { + if "Test" != findFormName(&FormValues{"_formName": {"Test"}}) { t.Error() } }) @@ -75,17 +75,17 @@ func Test_findFormName(t *testing.T) { func Test_findReplyTo(t *testing.T) { t.Run("No replyTo", func(t *testing.T) { - if "" != findReplyTo(FormValues{}) { + if "" != findReplyTo(&FormValues{}) { t.Error() } }) t.Run("Multiple replyTo", func(t *testing.T) { - if "" != findReplyTo(FormValues{"_replyTo": {"test@example.com", "test2@example.com"}}) { + if "" != findReplyTo(&FormValues{"_replyTo": {"test@example.com", "test2@example.com"}}) { t.Error() } }) t.Run("replyTo", func(t *testing.T) { - if "test@example.com" != findReplyTo(FormValues{"_replyTo": {"test@example.com"}}) { + if "test@example.com" != findReplyTo(&FormValues{"_replyTo": {"test@example.com"}}) { t.Error() } }) @@ -93,14 +93,14 @@ func Test_findReplyTo(t *testing.T) { func Test_removeMetaValues(t *testing.T) { t.Run("Remove meta values", func(t *testing.T) { - result := removeMetaValues(FormValues{ + result := removeMetaValues(&FormValues{ "_test": {"abc"}, "test": {"def"}, }) want := FormValues{ "test": {"def"}, } - if !reflect.DeepEqual(result, want) { + if !reflect.DeepEqual(*result, want) { t.Error() } }) @@ -113,7 +113,7 @@ func Test_buildMessage(t *testing.T) { _ = os.Setenv("ALLOWED_TO", "mail@example.com,test@example.com") _ = os.Setenv("EMAIL_FROM", "forms@example.com") appConfig, _ = parseConfig() - values := FormValues{ + values := &FormValues{ "_formName": {"Testform"}, "_replyTo": {"reply@example.com"}, "Testkey": {"Testvalue"}, @@ -134,4 +134,4 @@ func Test_buildMessage(t *testing.T) { t.Error() } }) -} \ No newline at end of file +} diff --git a/mailygo.go b/mailygo.go index 5ade801..40f770d 100644 --- a/mailygo.go +++ b/mailygo.go @@ -6,7 +6,7 @@ import ( "strconv" ) -var appConfig config +var appConfig *config func init() { cfg, err := parseConfig() diff --git a/spamcheck.go b/spamcheck.go index 9ac482f..6ce8aa5 100644 --- a/spamcheck.go +++ b/spamcheck.go @@ -1,16 +1,17 @@ package main import ( - "github.com/google/safebrowsing" "net/url" "strings" + + "github.com/google/safebrowsing" ) // Returns true when it spam -func checkValues(values FormValues) bool { +func checkValues(values *FormValues) bool { var urlsToCheck []string var allValues []string - for _, value := range values { + for _, value := range *values { for _, singleValue := range value { allValues = append(allValues, singleValue) if strings.Contains(singleValue, "http") { @@ -21,11 +22,11 @@ func checkValues(values FormValues) bool { } } } - return checkBlacklist(allValues) || checkUrls(urlsToCheck) + return checkBlacklist(&allValues) || checkUrls(&urlsToCheck) } -func checkBlacklist(values []string) bool { - for _, value := range values { +func checkBlacklist(values *[]string) bool { + for _, value := range *values { for _, blacklistedString := range appConfig.Blacklist { if strings.Contains(strings.ToLower(value), strings.ToLower(blacklistedString)) { return true @@ -38,8 +39,8 @@ func checkBlacklist(values []string) bool { // Only tests when GOOGLE_API_KEY is set // Returns true when it spam -func checkUrls(urlsToCheck []string) bool { - if len(appConfig.GoogleApiKey) < 1 || len(urlsToCheck) == 0 { +func checkUrls(urlsToCheck *[]string) bool { + if len(appConfig.GoogleApiKey) < 1 || len(*urlsToCheck) == 0 { return false } sb, err := safebrowsing.NewSafeBrowser(safebrowsing.Config{ @@ -49,7 +50,7 @@ func checkUrls(urlsToCheck []string) bool { if err != nil { return false } - allThreats, err := sb.LookupURLs(urlsToCheck) + allThreats, err := sb.LookupURLs(*urlsToCheck) if err != nil { return false } diff --git a/spamcheck_test.go b/spamcheck_test.go index 5b75282..7e2bc20 100644 --- a/spamcheck_test.go +++ b/spamcheck_test.go @@ -13,13 +13,13 @@ func Test_checkBlacklist(t *testing.T) { } t.Run("Allowed values", func(t *testing.T) { prepare() - if checkBlacklist([]string{"Hello", "How are you?"}) == true { + if checkBlacklist(&[]string{"Hello", "How are you?"}) == true { t.Error() } }) t.Run("Forbidden values", func(t *testing.T) { prepare() - if checkBlacklist([]string{"How are you?", "Hello TeSt1"}) == false { + if checkBlacklist(&[]string{"How are you?", "Hello TeSt1"}) == false { t.Error() } })