diff --git a/nibbler.go b/nibbler.go index 4ea2ae5..1503233 100644 --- a/nibbler.go +++ b/nibbler.go @@ -1,8 +1,6 @@ package go_nibbler -import ( - "strings" -) +import "strings" type state struct { InQuotes, PreviousDot, PreviousSlash, InDomain bool @@ -11,9 +9,9 @@ type state struct { const () const ( - ATEXT = "!#$%&'*+-/=?^_`.{|}~@\"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" + ATEXT = "!#$%&'*+-/=?^_`.{|}~@\"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞSSÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ÷ØÙÚÛÜÝÞŸàáâãäåæçèéêëìíîïðñòóôõö×øùúûüýþssàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ" SPECIAL = "(),:;<>[\\] " - HOSTNAME = "-.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" + HOSTNAME = "-.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞSSÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ÷ØÙÚÛÜÝÞŸàáâãäåæçèéêëìíîïðñòóôõö×øùúûüýþssàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿı" ) func ParseEmail(email string) (bool, string) { @@ -24,7 +22,10 @@ func ParseEmail(email string) (bool, string) { for offset, character := range email { // Local part if !currentState.InDomain { - if character == '\\' { + if character == ' ' { + valid = false + break + } else if character == '\\' { if currentState.InQuotes { // Check if slash was backslashed within quotes if currentState.PreviousSlash { @@ -38,13 +39,11 @@ func ParseEmail(email string) (bool, string) { break } } else if character == '"' { - if currentState.InQuotes { // Ignore if it was preceded by a backslash if !currentState.PreviousSlash { currentState.InQuotes = false } else { - // else: currentState.PreviousSlash = false } } else { @@ -58,6 +57,10 @@ func ParseEmail(email string) (bool, string) { } } else if character == '.' { // We can't have two consecutive dots + if !currentState.InQuotes && currentState.PreviousDot { + valid = false + break + } if !currentState.InQuotes { currentState.PreviousDot = true } @@ -90,17 +93,33 @@ func ParseEmail(email string) (bool, string) { currentState.PreviousDot = false } } else { + if character == '.' { + // We can't have two consecutive dots, even in the domain + if currentState.PreviousDot { + valid = false + break + } else { + currentState.PreviousDot = true + } + } if !strings.ContainsRune(HOSTNAME, character) { valid = false break } else { address += string(character) } + + // Check states and clear them if necessary + if currentState.PreviousSlash && character != '\\' { + currentState.PreviousSlash = false + } + if currentState.PreviousDot && character != '.' { + currentState.PreviousDot = false + } } } if !currentState.InDomain { valid = false } return valid, address - } diff --git a/nibbler_test.go b/nibbler_test.go index 2c8638b..8f24cba 100644 --- a/nibbler_test.go +++ b/nibbler_test.go @@ -11,10 +11,23 @@ type example struct { var examples = []example{ example{"woo", false, "woo"}, example{"woo@woot.com", true, "woo@woot.com"}, + example{"hoot@hoot-hoot.com", true, "hoot@hoot-hoot.com"}, example{"woo/+@blah.com", true, "woo/+@blah.com"}, example{"#!$%&'*+-/=?^_`{}|~@example.org", true, "#!$%&'*+-/=?^_`{}|~@example.org"}, + example{"üñîçøðé@üñîçøðéı.com", true, "üñîçøðé@üñîçøðéı.com"}, example{"\"Bob\" ", false, "\"Bob\""}, - // example{"bobthebuilder@176.2.0.234", false, "bobthebuilder@176.2.0.234"}, + example{"really.long.but.vaild.address@example.com", true, "really.long.but.vaild.address@example.com"}, + example{"johndoe@example.co.uk", true, "johndoe@example.co.uk"}, + example{"Bob bobthebuilder@dlc.com", false, "Bob"}, + example{"A@b@c@example.com", false, "A@b"}, + example{"a\"b(c)d,e:f;gi[j\\k]l@example.com", false, "a"}, + example{"[j\\k]l@example.com", false, ""}, + example{"john..doe@example.com", false, "john."}, + example{"john......doe@example.com", false, "john."}, + example{"john.doe@example..com", false, "john.doe@example."}, + example{"john.doe@exam_ple.com", false, "john.doe@exam"}, + example{" johndoe@example.com", false, ""}, + example{"johndoe@example.com ", false, "johndoe@example.com"}, } func TestNibbler(t *testing.T) {