parent
0acf824217
commit
428787d7ab
@ -0,0 +1,72 @@
|
||||
package stanza
|
||||
|
||||
import "encoding/xml"
|
||||
|
||||
// ============================================================================
|
||||
// SASLSuccess
|
||||
|
||||
type SASLSuccess struct {
|
||||
XMLName xml.Name `xml:"urn:ietf:params:xml:ns:xmpp-sasl success"`
|
||||
}
|
||||
|
||||
func (SASLSuccess) Name() string {
|
||||
return "sasl:success"
|
||||
}
|
||||
|
||||
type saslSuccessDecoder struct{}
|
||||
|
||||
var saslSuccess saslSuccessDecoder
|
||||
|
||||
func (saslSuccessDecoder) decode(p *xml.Decoder, se xml.StartElement) (SASLSuccess, error) {
|
||||
var packet SASLSuccess
|
||||
err := p.DecodeElement(&packet, &se)
|
||||
return packet, err
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// SASLFailure
|
||||
|
||||
type SASLFailure struct {
|
||||
XMLName xml.Name `xml:"urn:ietf:params:xml:ns:xmpp-sasl failure"`
|
||||
Any xml.Name // error reason is a subelement
|
||||
}
|
||||
|
||||
func (SASLFailure) Name() string {
|
||||
return "sasl:failure"
|
||||
}
|
||||
|
||||
type saslFailureDecoder struct{}
|
||||
|
||||
var saslFailure saslFailureDecoder
|
||||
|
||||
func (saslFailureDecoder) decode(p *xml.Decoder, se xml.StartElement) (SASLFailure, error) {
|
||||
var packet SASLFailure
|
||||
err := p.DecodeElement(&packet, &se)
|
||||
return packet, err
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
|
||||
type Auth struct {
|
||||
XMLName xml.Name `xml:"urn:ietf:params:xml:ns:xmpp-sasl auth"`
|
||||
Mechanism string `xml:"mecanism,attr"`
|
||||
Value string `xml:",innerxml"`
|
||||
}
|
||||
|
||||
type BindBind struct {
|
||||
XMLName xml.Name `xml:"urn:ietf:params:xml:ns:xmpp-bind bind"`
|
||||
Resource string `xml:"resource,omitempty"`
|
||||
Jid string `xml:"jid,omitempty"`
|
||||
}
|
||||
|
||||
func (b *BindBind) Namespace() string {
|
||||
return b.XMLName.Space
|
||||
}
|
||||
|
||||
// Session is obsolete in RFC 6121.
|
||||
// Added for compliance with RFC 3121.
|
||||
// Remove when ejabberd purely conforms to RFC 6121.
|
||||
type sessionSession struct {
|
||||
XMLName xml.Name `xml:"urn:ietf:params:xml:ns:xmpp-session session"`
|
||||
Optional xml.Name // If it does exist, it mean we are not required to open session
|
||||
}
|
@ -0,0 +1,89 @@
|
||||
package stanza
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
||||
)
|
||||
|
||||
// ============================================================================
|
||||
// Handshake Stanza
|
||||
|
||||
// Handshake is a stanza used by XMPP components to authenticate on XMPP
|
||||
// component port.
|
||||
type Handshake struct {
|
||||
XMLName xml.Name `xml:"jabber:component:accept handshake"`
|
||||
// TODO Add handshake value with test for proper serialization
|
||||
// Value string `xml:",innerxml"`
|
||||
}
|
||||
|
||||
func (Handshake) Name() string {
|
||||
return "component:handshake"
|
||||
}
|
||||
|
||||
// Handshake decoding wrapper
|
||||
|
||||
type handshakeDecoder struct{}
|
||||
|
||||
var handshake handshakeDecoder
|
||||
|
||||
func (handshakeDecoder) decode(p *xml.Decoder, se xml.StartElement) (Handshake, error) {
|
||||
var packet Handshake
|
||||
err := p.DecodeElement(&packet, &se)
|
||||
return packet, err
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Component delegation
|
||||
// XEP-0355
|
||||
|
||||
// Delegation can be used both on message (for delegated) and IQ (for Forwarded),
|
||||
// depending on the context.
|
||||
type Delegation struct {
|
||||
MsgExtension
|
||||
XMLName xml.Name `xml:"urn:xmpp:delegation:1 delegation"`
|
||||
Forwarded *Forwarded // This is used in iq to wrap delegated iqs
|
||||
Delegated *Delegated // This is used in a message to confirm delegated namespace
|
||||
}
|
||||
|
||||
func (d *Delegation) Namespace() string {
|
||||
return d.XMLName.Space
|
||||
}
|
||||
|
||||
type Forwarded struct {
|
||||
XMLName xml.Name `xml:"urn:xmpp:forward:0 forwarded"`
|
||||
Stanza Packet
|
||||
}
|
||||
|
||||
// UnmarshalXML is a custom unmarshal function used by xml.Unmarshal to
|
||||
// transform generic XML content into hierarchical Node structure.
|
||||
func (f *Forwarded) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
||||
// Check subelements to extract required field as boolean
|
||||
for {
|
||||
t, err := d.Token()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
switch tt := t.(type) {
|
||||
|
||||
case xml.StartElement:
|
||||
if packet, err := decodeClient(d, tt); err == nil {
|
||||
f.Stanza = packet
|
||||
}
|
||||
|
||||
case xml.EndElement:
|
||||
if tt == start.End() {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type Delegated struct {
|
||||
XMLName xml.Name `xml:"delegated"`
|
||||
Namespace string `xml:"namespace,attr,omitempty"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
TypeRegistry.MapExtension(PKTMessage, xml.Name{"urn:xmpp:delegation:1", "delegation"}, Delegation{})
|
||||
TypeRegistry.MapExtension(PKTIQ, xml.Name{"urn:xmpp:delegation:1", "delegation"}, Delegation{})
|
||||
}
|
@ -0,0 +1,79 @@
|
||||
package stanza
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// We should be able to properly parse delegation confirmation messages
|
||||
func TestParsingDelegationMessage(t *testing.T) {
|
||||
packetStr := `<message to='service.localhost' from='localhost'>
|
||||
<delegation xmlns='urn:xmpp:delegation:1'>
|
||||
<delegated namespace='http://jabber.org/protocol/pubsub'/>
|
||||
</delegation>
|
||||
</message>`
|
||||
var msg Message
|
||||
data := []byte(packetStr)
|
||||
if err := xml.Unmarshal(data, &msg); err != nil {
|
||||
t.Errorf("Unmarshal(%s) returned error", data)
|
||||
}
|
||||
|
||||
// Check that we have extracted the delegation info as MsgExtension
|
||||
var nsDelegated string
|
||||
for _, ext := range msg.Extensions {
|
||||
if delegation, ok := ext.(*Delegation); ok {
|
||||
nsDelegated = delegation.Delegated.Namespace
|
||||
}
|
||||
}
|
||||
if nsDelegated != "http://jabber.org/protocol/pubsub" {
|
||||
t.Errorf("Could not find delegated namespace in delegation: %#v\n", msg)
|
||||
}
|
||||
}
|
||||
|
||||
// Check that we can parse a delegation IQ.
|
||||
// The most important thing is to be able to
|
||||
func TestParsingDelegationIQ(t *testing.T) {
|
||||
packetStr := `<iq to='service.localhost' from='localhost' type='set' id='1'>
|
||||
<delegation xmlns='urn:xmpp:delegation:1'>
|
||||
<forwarded xmlns='urn:xmpp:forward:0'>
|
||||
<iq xml:lang='en' to='test1@localhost' from='test1@localhost/mremond-mbp' type='set' id='aaf3a' xmlns='jabber:client'>
|
||||
<pubsub xmlns='http://jabber.org/protocol/pubsub'>
|
||||
<publish node='http://jabber.org/protocol/mood'>
|
||||
<item id='current'>
|
||||
<mood xmlns='http://jabber.org/protocol/mood'>
|
||||
<excited/>
|
||||
</mood>
|
||||
</item>
|
||||
</publish>
|
||||
</pubsub>
|
||||
</iq>
|
||||
</forwarded>
|
||||
</delegation>
|
||||
</iq>`
|
||||
var iq IQ
|
||||
data := []byte(packetStr)
|
||||
if err := xml.Unmarshal(data, &iq); err != nil {
|
||||
t.Errorf("Unmarshal(%s) returned error", data)
|
||||
}
|
||||
|
||||
// Check that we have extracted the delegation info as IQPayload
|
||||
var node string
|
||||
if iq.Payload != nil {
|
||||
if delegation, ok := iq.Payload.(*Delegation); ok {
|
||||
packet := delegation.Forwarded.Stanza
|
||||
forwardedIQ, ok := packet.(IQ)
|
||||
if !ok {
|
||||
t.Errorf("Could not extract packet IQ")
|
||||
return
|
||||
}
|
||||
if forwardedIQ.Payload != nil {
|
||||
if pubsub, ok := forwardedIQ.Payload.(*PubSub); ok {
|
||||
node = pubsub.Publish.Node
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if node != "http://jabber.org/protocol/mood" {
|
||||
t.Errorf("Could not find mood node name on delegated publish: %#v\n", iq)
|
||||
}
|
||||
}
|
@ -1,14 +1,10 @@
|
||||
package xmpp
|
||||
package stanza
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
/*
|
||||
TODO support ability to put Raw payload inside IQ
|
||||
*/
|
||||
|
||||
// ============================================================================
|
||||
// XMPP Errors
|
||||
|
@ -1,4 +1,4 @@
|
||||
package xmpp
|
||||
package stanza
|
||||
|
||||
// ErrorType is a Enum of error attribute type
|
||||
type ErrorType string
|
@ -1,4 +1,4 @@
|
||||
package xmpp
|
||||
package stanza
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
@ -1,4 +1,4 @@
|
||||
package xmpp
|
||||
package stanza
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
@ -1,4 +1,4 @@
|
||||
package xmpp
|
||||
package stanza
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
@ -1,6 +1,8 @@
|
||||
package xmpp
|
||||
package stanza
|
||||
|
||||
import "encoding/xml"
|
||||
import (
|
||||
"encoding/xml"
|
||||
)
|
||||
|
||||
/*
|
||||
Support for:
|
@ -1,6 +1,8 @@
|
||||
package xmpp
|
||||
package stanza
|
||||
|
||||
import "encoding/xml"
|
||||
import (
|
||||
"encoding/xml"
|
||||
)
|
||||
|
||||
/*
|
||||
Support for:
|
@ -1,6 +1,8 @@
|
||||
package xmpp
|
||||
package stanza
|
||||
|
||||
import "encoding/xml"
|
||||
import (
|
||||
"encoding/xml"
|
||||
)
|
||||
|
||||
type HTML struct {
|
||||
MsgExtension
|
@ -1,6 +1,8 @@
|
||||
package xmpp
|
||||
package stanza
|
||||
|
||||
import "encoding/xml"
|
||||
import (
|
||||
"encoding/xml"
|
||||
)
|
||||
|
||||
/*
|
||||
Support for:
|
@ -1,6 +1,8 @@
|
||||
package xmpp
|
||||
package stanza
|
||||
|
||||
import "encoding/xml"
|
||||
import (
|
||||
"encoding/xml"
|
||||
)
|
||||
|
||||
/*
|
||||
Support for:
|
@ -0,0 +1,51 @@
|
||||
package stanza
|
||||
|
||||
import "encoding/xml"
|
||||
|
||||
// ============================================================================
|
||||
// Generic / unknown content
|
||||
|
||||
// Node is a generic structure to represent XML data. It is used to parse
|
||||
// unreferenced or custom stanza payload.
|
||||
type Node struct {
|
||||
XMLName xml.Name
|
||||
Attrs []xml.Attr `xml:"-"`
|
||||
Content string `xml:",innerxml"`
|
||||
Nodes []Node `xml:",any"`
|
||||
}
|
||||
|
||||
func (n *Node) Namespace() string {
|
||||
return n.XMLName.Space
|
||||
}
|
||||
|
||||
// Attr represents generic XML attributes, as used on the generic XML Node
|
||||
// representation.
|
||||
type Attr struct {
|
||||
K string
|
||||
V string
|
||||
}
|
||||
|
||||
// UnmarshalXML is a custom unmarshal function used by xml.Unmarshal to
|
||||
// transform generic XML content into hierarchical Node structure.
|
||||
func (n *Node) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
||||
// Assign "n.Attrs = start.Attr", without repeating xmlns in attributes:
|
||||
for _, attr := range start.Attr {
|
||||
// Do not repeat xmlns, it is already in XMLName
|
||||
if attr.Name.Local != "xmlns" {
|
||||
n.Attrs = append(n.Attrs, attr)
|
||||
}
|
||||
}
|
||||
type node Node
|
||||
return d.DecodeElement((*node)(n), &start)
|
||||
}
|
||||
|
||||
// MarshalXML is a custom XML serializer used by xml.Marshal to serialize a
|
||||
// Node structure to XML.
|
||||
func (n Node) MarshalXML(e *xml.Encoder, start xml.StartElement) (err error) {
|
||||
start.Attr = n.Attrs
|
||||
start.Name = n.XMLName
|
||||
|
||||
err = e.EncodeToken(start)
|
||||
e.EncodeElement(n.Nodes, xml.StartElement{Name: n.XMLName})
|
||||
return e.EncodeToken(xml.EndElement{Name: start.Name})
|
||||
}
|
@ -1,11 +1,11 @@
|
||||
package xmpp
|
||||
package stanza
|
||||
|
||||
const (
|
||||
NSStream = "http://etherx.jabber.org/streams"
|
||||
nsTLS = "urn:ietf:params:xml:ns:xmpp-tls"
|
||||
nsSASL = "urn:ietf:params:xml:ns:xmpp-sasl"
|
||||
nsBind = "urn:ietf:params:xml:ns:xmpp-bind"
|
||||
nsSession = "urn:ietf:params:xml:ns:xmpp-session"
|
||||
NSSASL = "urn:ietf:params:xml:ns:xmpp-sasl"
|
||||
NSBind = "urn:ietf:params:xml:ns:xmpp-bind"
|
||||
NSSession = "urn:ietf:params:xml:ns:xmpp-session"
|
||||
NSClient = "jabber:client"
|
||||
NSComponent = "jabber:component:accept"
|
||||
)
|
@ -1,4 +1,4 @@
|
||||
package xmpp
|
||||
package stanza
|
||||
|
||||
type Packet interface {
|
||||
Name() string
|
@ -1,4 +1,4 @@
|
||||
package xmpp
|
||||
package stanza
|
||||
|
||||
type StanzaType string
|
||||
|
@ -1,4 +1,4 @@
|
||||
package xmpp
|
||||
package stanza
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
@ -1,4 +1,4 @@
|
||||
package xmpp
|
||||
package stanza
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
@ -1,4 +1,4 @@
|
||||
package xmpp
|
||||
package stanza
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
@ -1,4 +1,4 @@
|
||||
package xmpp
|
||||
package stanza
|
||||
|
||||
// PresenceShow is a Enum of presence element show
|
||||
type PresenceShow string
|
@ -1,4 +1,4 @@
|
||||
package xmpp
|
||||
package stanza
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
@ -1,4 +1,4 @@
|
||||
package xmpp
|
||||
package stanza
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
@ -1,4 +1,4 @@
|
||||
package xmpp
|
||||
package stanza
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
@ -1,4 +1,4 @@
|
||||
package xmpp
|
||||
package stanza
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
@ -1,4 +1,4 @@
|
||||
package xmpp_test
|
||||
package stanza_test
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
Loading…
Reference in new issue