go-xmpp/stanza/jid.go
remicorniere 947fcf0432 PubSub protocol support (#142)
* PubSub protocol support
Added support for :
- XEP-0050   (Command))
- XEP-0060   (PubSub)
- XEP-0004   (Forms)

Fixed the NewClient function by adding parsing of the domain from the JID if no domain is provided in transport config.
Updated xmpp_jukebox example

* Delete useless pubsub errors

* README.md update
Fixed import in echo example

* Typo

* Fixed raw send on client example

* Fixed jukebox example and added a README.md
2020-01-09 15:33:11 +01:00

92 lines
1.9 KiB
Go

package stanza
import (
"fmt"
"strings"
"unicode"
)
type Jid struct {
Node string
Domain string
Resource string
}
func NewJid(sjid string) (*Jid, error) {
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.Node = s1[0]
if s1[1] == "" {
return jid, fmt.Errorf("domain cannot be empty")
}
jid.Domain = s1[1]
}
// 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.Node) {
return jid, fmt.Errorf("invalid Node in Jid '%s'", sjid)
}
if !isDomainValid(jid.Domain) {
return jid, fmt.Errorf("invalid domain in Jid '%s'", sjid)
}
return jid, nil
}
func (j *Jid) Full() string {
return j.Node + "@" + j.Domain + "/" + j.Resource
}
func (j *Jid) Bare() string {
return j.Node + "@" + j.Domain
}
// ============================================================================
// Helpers, for parsing / validation
func isUsernameValid(username string) bool {
invalidRunes := []rune{'@', '/', '\'', '"', ':', '<', '>'}
return strings.IndexFunc(username, isInvalid(invalidRunes)) < 0
}
func isDomainValid(domain string) bool {
if len(domain) == 0 {
return false
}
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
}