structs.go
changeset 36 9fe022261dcc
parent 34 7b1f924c75e2
child 37 fbda8e925fdf
--- a/structs.go	Fri Dec 30 18:25:08 2011 -0700
+++ b/structs.go	Fri Dec 30 21:49:00 2011 -0700
@@ -95,6 +95,11 @@
 	XError() *Error
 	// A (non-error) nested element, if any.
 	XChild() *Generic
+	innerxml() string
+}
+
+type ExtendedStanza interface {
+	InnerMarshal(io.Writer) os.Error
 }
 
 // message stanza
@@ -104,6 +109,7 @@
 	Id string `xml:"attr"`
 	Type string `xml:"attr"`
 	Lang string `xml:"attr"`
+	Innerxml string `xml:"innerxml"`
 	Error *Error
 	Subject *Generic
 	Body *Generic
@@ -112,6 +118,7 @@
 }
 var _ xml.Marshaler = &Message{}
 var _ Stanza = &Message{}
+var _ ExtendedStanza = &Message{}
 
 // presence stanza
 type Presence struct {
@@ -120,6 +127,7 @@
 	Id string `xml:"attr"`
 	Type string `xml:"attr"`
 	Lang string `xml:"attr"`
+	Innerxml string `xml:"innerxml"`
 	Error *Error
 	Show *Generic
 	Status *Generic
@@ -128,6 +136,7 @@
 }
 var _ xml.Marshaler = &Presence{}
 var _ Stanza = &Presence{}
+var _ ExtendedStanza = &Presence{}
 
 // iq stanza
 type Iq struct {
@@ -136,30 +145,13 @@
 	Id string `xml:"attr"`
 	Type string `xml:"attr"`
 	Lang string `xml:"attr"`
+	Innerxml string `xml:"innerxml"`
 	Error *Error
 	Any *Generic
-	Query *RosterQuery
 }
 var _ xml.Marshaler = &Iq{}
 var _ Stanza = &Iq{}
 
-// Roster query/result
-type RosterQuery struct {
-	// Should always be query in the NsRoster namespace
-	XMLName xml.Name
-	Item []RosterItem
-}
-
-// See RFC 3921, Section 7.1.
-type RosterItem struct {
-	// Should always be "item"
-	XMLName xml.Name
-	Jid string `xml:"attr"`
-	Subscription string `xml:"attr"`
-	Name string `xml:"attr"`
-	Group []string
-}
-
 // Describes an XMPP stanza error. See RFC 3920, Section 9.3.
 type Error struct {
 	// The error type attribute.
@@ -282,8 +274,6 @@
 		u.XMLName.Local)
 }
 
-// BUG(cjyar) This is fragile. We should find a way to use go's native
-// XML marshaling.
 func marshalXML(st Stanza) ([]byte, os.Error) {
 	buf := bytes.NewBuffer(nil)
 	buf.WriteString("<")
@@ -304,15 +294,22 @@
 		writeField(buf, "xml:lang", st.XLang())
 	}
 	buf.WriteString(">")
-	if st.XError() != nil {
-		bytes, _ := st.XError().MarshalXML()
-		buf.WriteString(string(bytes))
-	}
-	if st.XChild() != nil {
-		xml.Marshal(buf, st.XChild())
-	}
-	if iq, ok := st.(*Iq) ; ok && iq.Query != nil {
-		xml.Marshal(buf, iq.Query)
+	if ext, ok := st.(ExtendedStanza) ; ok {
+		if st.XError() != nil {
+			bytes, _ := st.XError().MarshalXML()
+			buf.WriteString(string(bytes))
+		}
+		err := ext.InnerMarshal(buf)
+		if err != nil {
+			return nil, err
+		}
+	} else {
+		inner := st.innerxml()
+		if inner == "" {
+			xml.Marshal(buf, st.XChild())
+		} else {
+			buf.WriteString(st.innerxml())
+		}
 	}
 	buf.WriteString("</")
 	buf.WriteString(st.XName())
@@ -369,10 +366,30 @@
 	return m.Any
 }
 
+func (m *Message) innerxml() string {
+	return m.Innerxml
+}
+
 func (m *Message) MarshalXML() ([]byte, os.Error) {
 	return marshalXML(m)
 }
 
+func (m *Message) InnerMarshal(w io.Writer) os.Error {
+	err := xml.Marshal(w, m.Subject)
+	if err != nil {
+		return err
+	}
+	err = xml.Marshal(w, m.Body)
+	if err != nil {
+		return err
+	}
+	err = xml.Marshal(w, m.Thread)
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
 func (p *Presence) XName() string {
 	return "presence"
 }
@@ -405,10 +422,30 @@
 	return p.Any
 }
 
+func (p *Presence) innerxml() string {
+	return p.Innerxml
+}
+
 func (p *Presence) MarshalXML() ([]byte, os.Error) {
 	return marshalXML(p)
 }
 
+func (p *Presence) InnerMarshal(w io.Writer) os.Error {
+	err := xml.Marshal(w, p.Show)
+	if err != nil {
+		return err
+	}
+	err = xml.Marshal(w, p.Status)
+	if err != nil {
+		return err
+	}
+	err = xml.Marshal(w, p.Priority)
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
 func (iq *Iq) XName() string {
 	return "iq"
 }
@@ -441,6 +478,10 @@
 	return iq.Any
 }
 
+func (iq *Iq) innerxml() string {
+	return iq.Innerxml
+}
+
 func (iq *Iq) MarshalXML() ([]byte, os.Error) {
 	return marshalXML(iq)
 }