parent
80d8d6d231
commit
b93a3a2550
51
jid.go
51
jid.go
|
@ -3,6 +3,7 @@ package xmpp // import "gosrc.io/xmpp"
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"strings"
|
"strings"
|
||||||
|
"unicode"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Jid struct {
|
type Jid struct {
|
||||||
|
@ -11,24 +12,52 @@ type Jid struct {
|
||||||
resource string
|
resource string
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewJid(sjid string) (jid *Jid, err error) {
|
func NewJid(sjid string) (*Jid, error) {
|
||||||
s1 := strings.Split(sjid, "@")
|
s1 := strings.SplitN(sjid, "@", 2)
|
||||||
if len(s1) != 2 {
|
if len(s1) != 2 {
|
||||||
err = errors.New("invalid JID: " + sjid)
|
return nil, errors.New("invalid JID, missing domain: " + sjid)
|
||||||
return
|
|
||||||
}
|
}
|
||||||
jid = new(Jid)
|
jid := new(Jid)
|
||||||
jid.username = s1[0]
|
jid.username = s1[0]
|
||||||
|
if !isUsernameValid(jid.username) {
|
||||||
s2 := strings.Split(s1[1], "/")
|
return jid, errors.New("invalid domain: " + jid.username)
|
||||||
if len(s2) > 2 {
|
|
||||||
err = errors.New("invalid JID: " + sjid)
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s2 := strings.SplitN(s1[1], "/", 2)
|
||||||
|
|
||||||
jid.domain = s2[0]
|
jid.domain = s2[0]
|
||||||
|
if !isDomainValid(jid.domain) {
|
||||||
|
return jid, errors.New("invalid domain: " + jid.domain)
|
||||||
|
}
|
||||||
|
|
||||||
if len(s2) == 2 {
|
if len(s2) == 2 {
|
||||||
jid.resource = s2[1]
|
jid.resource = s2[1]
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return jid, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func isUsernameValid(username string) bool {
|
||||||
|
invalidRunes := []rune{'@', '/', '\'', '"', ':', '<', '>'}
|
||||||
|
return strings.IndexFunc(username, isInvalid(invalidRunes)) < 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func isDomainValid(domain string) bool {
|
||||||
|
invalidRunes := []rune{'@', '/'}
|
||||||
|
return strings.IndexFunc(domain, isInvalid(invalidRunes)) < 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func isInvalid(invalidRunes []rune) func(c rune) bool {
|
||||||
|
isInvalid := func(c rune) bool {
|
||||||
|
if unicode.IsSpace(c) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
for _, r := range invalidRunes {
|
||||||
|
if c == r {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return isInvalid
|
||||||
}
|
}
|
||||||
|
|
48
jid_test.go
48
jid_test.go
|
@ -5,43 +5,49 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestValidJids(t *testing.T) {
|
func TestValidJids(t *testing.T) {
|
||||||
var jid *Jid
|
tests := []struct {
|
||||||
var err error
|
jidstr string
|
||||||
|
expected Jid
|
||||||
|
}{
|
||||||
|
{jidstr: "test@domain.com", expected: Jid{"test", "domain.com", ""}},
|
||||||
|
{jidstr: "test@domain.com/resource", expected: Jid{"test", "domain.com", "resource"}},
|
||||||
|
// 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"}},
|
||||||
|
}
|
||||||
|
|
||||||
goodJids := []string{"test@domain.com", "test@domain.com/resource"}
|
for _, tt := range tests {
|
||||||
|
jid, err := NewJid(tt.jidstr)
|
||||||
for i, sjid := range goodJids {
|
if err != nil {
|
||||||
if jid, err = NewJid(sjid); err != nil {
|
t.Errorf("could not parse correct jid: %s", tt.jidstr)
|
||||||
t.Error("could not parse correct jid")
|
continue
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if jid == nil {
|
if jid == nil {
|
||||||
t.Error("jid should not be nil")
|
t.Error("jid should not be nil")
|
||||||
}
|
}
|
||||||
|
|
||||||
if jid.username != "test" {
|
if jid.username != tt.expected.username {
|
||||||
t.Error("incorrect jid username")
|
t.Errorf("incorrect jid username (%s): %s", tt.expected.username, jid.username)
|
||||||
}
|
}
|
||||||
|
|
||||||
if jid.domain != "domain.com" {
|
if jid.username != tt.expected.username {
|
||||||
t.Error("incorrect jid domain")
|
t.Errorf("incorrect jid domain (%s): %s", tt.expected.domain, jid.domain)
|
||||||
}
|
}
|
||||||
|
|
||||||
if i == 0 && jid.resource != "" {
|
if jid.resource != tt.expected.resource {
|
||||||
t.Error("bare jid resource should be empty")
|
t.Errorf("incorrect jid resource (%s): %s", tt.expected.resource, jid.resource)
|
||||||
}
|
|
||||||
|
|
||||||
if i == 1 && jid.resource != "resource" {
|
|
||||||
t.Error("incorrect full jid resource")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Check if resource cannot contain a /
|
|
||||||
func TestIncorrectJids(t *testing.T) {
|
func TestIncorrectJids(t *testing.T) {
|
||||||
badJids := []string{"test@domain.com@otherdomain.com",
|
badJids := []string{
|
||||||
"test@domain.com/test/test"}
|
"user:name@domain.com",
|
||||||
|
"user<name@domain.com",
|
||||||
|
"test@domain.com@otherdomain.com",
|
||||||
|
"test@domain com/resource",
|
||||||
|
}
|
||||||
|
|
||||||
for _, sjid := range badJids {
|
for _, sjid := range badJids {
|
||||||
if _, err := NewJid(sjid); err == nil {
|
if _, err := NewJid(sjid); err == nil {
|
||||||
|
|
Loading…
Reference in a new issue