mirror of https://github.com/FluuxIO/go-xmpp
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
149 lines
3.4 KiB
Go
149 lines
3.4 KiB
Go
5 years ago
|
package stanza
|
||
9 years ago
|
|
||
|
import (
|
||
|
"encoding/xml"
|
||
5 years ago
|
"reflect"
|
||
9 years ago
|
)
|
||
|
|
||
7 years ago
|
// ============================================================================
|
||
|
// Message Packet
|
||
|
|
||
5 years ago
|
// Message implements RFC 6120 - A.5 Client Namespace (a part)
|
||
7 years ago
|
type Message struct {
|
||
|
XMLName xml.Name `xml:"message"`
|
||
5 years ago
|
Attrs
|
||
|
|
||
5 years ago
|
Subject string `xml:"subject,omitempty"`
|
||
|
Body string `xml:"body,omitempty"`
|
||
|
Thread string `xml:"thread,omitempty"`
|
||
|
Error Err `xml:"error,omitempty"`
|
||
|
Extensions []MsgExtension `xml:",omitempty"`
|
||
9 years ago
|
}
|
||
|
|
||
7 years ago
|
func (Message) Name() string {
|
||
|
return "message"
|
||
|
}
|
||
|
|
||
5 years ago
|
func NewMessage(a Attrs) Message {
|
||
7 years ago
|
return Message{
|
||
|
XMLName: xml.Name{Local: "message"},
|
||
5 years ago
|
Attrs: a,
|
||
7 years ago
|
}
|
||
|
}
|
||
|
|
||
5 years ago
|
// Get search and extracts a specific extension on a message.
|
||
|
// It receives a pointer to an MsgExtension. It will panic if the caller
|
||
|
// does not pass a pointer.
|
||
|
// It will return true if the passed extension is found and set the pointer
|
||
|
// to the extension passed as parameter to the found extension.
|
||
|
// It will return false if the extension is not found on the message.
|
||
|
//
|
||
|
// Example usage:
|
||
|
// var oob xmpp.OOB
|
||
|
// if ok := msg.Get(&oob); ok {
|
||
|
// // oob extension has been found
|
||
|
// }
|
||
|
func (msg *Message) Get(ext MsgExtension) bool {
|
||
|
target := reflect.ValueOf(ext)
|
||
|
if target.Kind() != reflect.Ptr {
|
||
|
panic("you must pass a pointer to the message Get method")
|
||
|
}
|
||
|
|
||
|
for _, e := range msg.Extensions {
|
||
|
if reflect.TypeOf(e) == target.Type() {
|
||
|
source := reflect.ValueOf(e)
|
||
|
if source.Kind() != reflect.Ptr {
|
||
|
source = source.Elem()
|
||
|
}
|
||
|
target.Elem().Set(source.Elem())
|
||
|
return true
|
||
|
}
|
||
|
}
|
||
|
return false
|
||
|
}
|
||
|
|
||
7 years ago
|
type messageDecoder struct{}
|
||
|
|
||
|
var message messageDecoder
|
||
9 years ago
|
|
||
7 years ago
|
func (messageDecoder) decode(p *xml.Decoder, se xml.StartElement) (Message, error) {
|
||
|
var packet Message
|
||
|
err := p.DecodeElement(&packet, &se)
|
||
|
return packet, err
|
||
|
}
|
||
|
|
||
5 years ago
|
// XMPPFormat with all Extensions
|
||
7 years ago
|
func (msg *Message) XMPPFormat() string {
|
||
5 years ago
|
out, err := xml.MarshalIndent(msg, "", "")
|
||
|
if err != nil {
|
||
|
return ""
|
||
|
}
|
||
|
return string(out)
|
||
9 years ago
|
}
|
||
5 years ago
|
|
||
5 years ago
|
// UnmarshalXML implements custom parsing for messages
|
||
5 years ago
|
func (msg *Message) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
||
|
msg.XMLName = start.Name
|
||
|
|
||
|
// Extract packet attributes
|
||
|
for _, attr := range start.Attr {
|
||
|
if attr.Name.Local == "id" {
|
||
|
msg.Id = attr.Value
|
||
|
}
|
||
|
if attr.Name.Local == "type" {
|
||
5 years ago
|
msg.Type = StanzaType(attr.Value)
|
||
5 years ago
|
}
|
||
|
if attr.Name.Local == "to" {
|
||
|
msg.To = attr.Value
|
||
|
}
|
||
|
if attr.Name.Local == "from" {
|
||
|
msg.From = attr.Value
|
||
|
}
|
||
|
if attr.Name.Local == "lang" {
|
||
|
msg.Lang = attr.Value
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// decode inner elements
|
||
|
for {
|
||
|
t, err := d.Token()
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
switch tt := t.(type) {
|
||
|
|
||
|
case xml.StartElement:
|
||
5 years ago
|
if msgExt := TypeRegistry.GetMsgExtension(tt.Name); msgExt != nil {
|
||
5 years ago
|
// Decode message extension
|
||
|
err = d.DecodeElement(msgExt, &tt)
|
||
|
if err != nil {
|
||
|
return err
|
||
5 years ago
|
}
|
||
5 years ago
|
msg.Extensions = append(msg.Extensions, msgExt)
|
||
5 years ago
|
} else {
|
||
5 years ago
|
// Decode standard message sub-elements
|
||
5 years ago
|
var err error
|
||
|
switch tt.Name.Local {
|
||
|
case "body":
|
||
|
err = d.DecodeElement(&msg.Body, &tt)
|
||
|
case "thread":
|
||
|
err = d.DecodeElement(&msg.Thread, &tt)
|
||
|
case "subject":
|
||
|
err = d.DecodeElement(&msg.Subject, &tt)
|
||
|
case "error":
|
||
|
err = d.DecodeElement(&msg.Error, &tt)
|
||
|
}
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
}
|
||
|
|
||
|
case xml.EndElement:
|
||
|
if tt == start.End() {
|
||
|
return nil
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|