Further improvements on JID parsing
This commit is contained in:
parent
3ccc2680b0
commit
b8fdc510a6
43
jid.go
43
jid.go
|
@ -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,25 +13,38 @@ 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)
|
||||||
|
|
||||||
|
if sjid == "" {
|
||||||
|
return jid, fmt.Errorf("jid cannot be empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
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]
|
jid.username = s1[0]
|
||||||
if !isUsernameValid(jid.username) {
|
if s1[1] == "" {
|
||||||
return jid, errors.New("invalid domain: " + jid.username)
|
return jid, fmt.Errorf("domain cannot be empty")
|
||||||
|
}
|
||||||
|
jid.domain = s1[1]
|
||||||
}
|
}
|
||||||
|
|
||||||
s2 := strings.SplitN(s1[1], "/", 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.domain = s2[0]
|
||||||
if !isDomainValid(jid.domain) {
|
jid.resource = s2[1]
|
||||||
return jid, errors.New("invalid domain: " + jid.domain)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(s2) == 2 {
|
if !isUsernameValid(jid.username) {
|
||||||
jid.resource = s2[1]
|
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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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",
|
||||||
|
|
Loading…
Reference in a new issue