Further improvements on JID parsing

This commit is contained in:
Mickael Remond 2019-06-07 11:40:10 +02:00
parent 3ccc2680b0
commit b8fdc510a6
No known key found for this signature in database
GPG key ID: E6F6045D79965AA3
2 changed files with 35 additions and 14 deletions

45
jid.go
View file

@ -1,7 +1,7 @@
package xmpp // import "gosrc.io/xmpp" package xmpp // import "gosrc.io/xmpp"
import ( import (
"errors" "fmt"
"strings" "strings"
"unicode" "unicode"
) )
@ -13,27 +13,40 @@ type Jid struct {
} }
func NewJid(sjid string) (*Jid, error) { 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 := new(Jid)
jid.username = s1[0]
if !isUsernameValid(jid.username) { if sjid == "" {
return jid, errors.New("invalid domain: " + jid.username) return jid, fmt.Errorf("jid cannot be empty")
} }
s2 := strings.SplitN(s1[1], "/", 2) s1 := strings.SplitN(sjid, "@", 2)
if len(s1) == 1 { // This is a server or component JID
jid.domain = s2[0] jid.domain = s1[0]
if !isDomainValid(jid.domain) { } else { // JID has a local username part
return jid, errors.New("invalid domain: " + jid.domain) 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] 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 return jid, nil
} }
@ -43,6 +56,10 @@ func isUsernameValid(username string) bool {
} }
func isDomainValid(domain string) bool { func isDomainValid(domain string) bool {
if len(domain) == 0 {
return false
}
invalidRunes := []rune{'@', '/'} invalidRunes := []rune{'@', '/'}
return strings.IndexFunc(domain, isInvalid(invalidRunes)) < 0 return strings.IndexFunc(domain, isInvalid(invalidRunes)) < 0
} }

View file

@ -14,6 +14,7 @@ func TestValidJids(t *testing.T) {
// resource can contain '/' or '@' // 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: "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 { for _, tt := range tests {
@ -43,6 +44,9 @@ func TestValidJids(t *testing.T) {
func TestIncorrectJids(t *testing.T) { func TestIncorrectJids(t *testing.T) {
badJids := []string{ badJids := []string{
"",
"user@",
"@domain.com",
"user:name@domain.com", "user:name@domain.com",
"user<name@domain.com", "user<name@domain.com",
"test@domain.com@otherdomain.com", "test@domain.com@otherdomain.com",