From b8fdc510a68ed068e47a480494a51900af381941 Mon Sep 17 00:00:00 2001 From: Mickael Remond Date: Fri, 7 Jun 2019 11:40:10 +0200 Subject: [PATCH] Further improvements on JID parsing --- jid.go | 45 +++++++++++++++++++++++++++++++-------------- jid_test.go | 4 ++++ 2 files changed, 35 insertions(+), 14 deletions(-) diff --git a/jid.go b/jid.go index 9594fbd..e025911 100644 --- a/jid.go +++ b/jid.go @@ -1,7 +1,7 @@ package xmpp // import "gosrc.io/xmpp" import ( - "errors" + "fmt" "strings" "unicode" ) @@ -13,27 +13,40 @@ type Jid struct { } func NewJid(sjid string) (*Jid, error) { - s1 := strings.SplitN(sjid, "@", 2) - if len(s1) != 2 { - return nil, errors.New("invalid JID, missing domain: " + sjid) - } jid := new(Jid) - jid.username = s1[0] - if !isUsernameValid(jid.username) { - return jid, errors.New("invalid domain: " + jid.username) + + if sjid == "" { + return jid, fmt.Errorf("jid cannot be empty") } - s2 := strings.SplitN(s1[1], "/", 2) - - jid.domain = s2[0] - if !isDomainValid(jid.domain) { - return jid, errors.New("invalid domain: " + jid.domain) + s1 := strings.SplitN(sjid, "@", 2) + if len(s1) == 1 { // This is a server or component JID + jid.domain = s1[0] + } else { // JID has a local username part + if s1[0] == "" { + return jid, fmt.Errorf("invalid jid '%s", sjid) + } + jid.username = s1[0] + if s1[1] == "" { + return jid, fmt.Errorf("domain cannot be empty") + } + jid.domain = s1[1] } - if len(s2) == 2 { + // Extract resource from domain field + s2 := strings.SplitN(jid.domain, "/", 2) + if len(s2) == 2 { // If len = 1, domain is already correct, and resource is already empty + jid.domain = s2[0] jid.resource = s2[1] } + if !isUsernameValid(jid.username) { + return jid, fmt.Errorf("invalid username in JID '%s'", sjid) + } + if !isDomainValid(jid.domain) { + return jid, fmt.Errorf("invalid domain in JID '%s'", sjid) + } + return jid, nil } @@ -43,6 +56,10 @@ func isUsernameValid(username string) bool { } func isDomainValid(domain string) bool { + if len(domain) == 0 { + return false + } + invalidRunes := []rune{'@', '/'} return strings.IndexFunc(domain, isInvalid(invalidRunes)) < 0 } diff --git a/jid_test.go b/jid_test.go index d74543f..4b27de4 100644 --- a/jid_test.go +++ b/jid_test.go @@ -14,6 +14,7 @@ func TestValidJids(t *testing.T) { // resource can contain '/' or '@' {jidstr: "test@domain.com/a/b", expected: Jid{"test", "domain.com", "a/b"}}, {jidstr: "test@domain.com/a@b", expected: Jid{"test", "domain.com", "a@b"}}, + {jidstr: "domain.com", expected: Jid{"", "domain.com", ""}}, } for _, tt := range tests { @@ -43,6 +44,9 @@ func TestValidJids(t *testing.T) { func TestIncorrectJids(t *testing.T) { badJids := []string{ + "", + "user@", + "@domain.com", "user:name@domain.com", "user