93 XLang() string |
93 XLang() string |
94 // A nested error element, if any. |
94 // A nested error element, if any. |
95 XError() *Error |
95 XError() *Error |
96 // A (non-error) nested element, if any. |
96 // A (non-error) nested element, if any. |
97 XChild() *Generic |
97 XChild() *Generic |
|
98 innerxml() string |
|
99 } |
|
100 |
|
101 type ExtendedStanza interface { |
|
102 InnerMarshal(io.Writer) os.Error |
98 } |
103 } |
99 |
104 |
100 // message stanza |
105 // message stanza |
101 type Message struct { |
106 type Message struct { |
102 To string `xml:"attr"` |
107 To string `xml:"attr"` |
103 From string `xml:"attr"` |
108 From string `xml:"attr"` |
104 Id string `xml:"attr"` |
109 Id string `xml:"attr"` |
105 Type string `xml:"attr"` |
110 Type string `xml:"attr"` |
106 Lang string `xml:"attr"` |
111 Lang string `xml:"attr"` |
|
112 Innerxml string `xml:"innerxml"` |
107 Error *Error |
113 Error *Error |
108 Subject *Generic |
114 Subject *Generic |
109 Body *Generic |
115 Body *Generic |
110 Thread *Generic |
116 Thread *Generic |
111 Any *Generic |
117 Any *Generic |
112 } |
118 } |
113 var _ xml.Marshaler = &Message{} |
119 var _ xml.Marshaler = &Message{} |
114 var _ Stanza = &Message{} |
120 var _ Stanza = &Message{} |
|
121 var _ ExtendedStanza = &Message{} |
115 |
122 |
116 // presence stanza |
123 // presence stanza |
117 type Presence struct { |
124 type Presence struct { |
118 To string `xml:"attr"` |
125 To string `xml:"attr"` |
119 From string `xml:"attr"` |
126 From string `xml:"attr"` |
120 Id string `xml:"attr"` |
127 Id string `xml:"attr"` |
121 Type string `xml:"attr"` |
128 Type string `xml:"attr"` |
122 Lang string `xml:"attr"` |
129 Lang string `xml:"attr"` |
|
130 Innerxml string `xml:"innerxml"` |
123 Error *Error |
131 Error *Error |
124 Show *Generic |
132 Show *Generic |
125 Status *Generic |
133 Status *Generic |
126 Priority *Generic |
134 Priority *Generic |
127 Any *Generic |
135 Any *Generic |
128 } |
136 } |
129 var _ xml.Marshaler = &Presence{} |
137 var _ xml.Marshaler = &Presence{} |
130 var _ Stanza = &Presence{} |
138 var _ Stanza = &Presence{} |
|
139 var _ ExtendedStanza = &Presence{} |
131 |
140 |
132 // iq stanza |
141 // iq stanza |
133 type Iq struct { |
142 type Iq struct { |
134 To string `xml:"attr"` |
143 To string `xml:"attr"` |
135 From string `xml:"attr"` |
144 From string `xml:"attr"` |
136 Id string `xml:"attr"` |
145 Id string `xml:"attr"` |
137 Type string `xml:"attr"` |
146 Type string `xml:"attr"` |
138 Lang string `xml:"attr"` |
147 Lang string `xml:"attr"` |
|
148 Innerxml string `xml:"innerxml"` |
139 Error *Error |
149 Error *Error |
140 Any *Generic |
150 Any *Generic |
141 Query *RosterQuery |
|
142 } |
151 } |
143 var _ xml.Marshaler = &Iq{} |
152 var _ xml.Marshaler = &Iq{} |
144 var _ Stanza = &Iq{} |
153 var _ Stanza = &Iq{} |
145 |
|
146 // Roster query/result |
|
147 type RosterQuery struct { |
|
148 // Should always be query in the NsRoster namespace |
|
149 XMLName xml.Name |
|
150 Item []RosterItem |
|
151 } |
|
152 |
|
153 // See RFC 3921, Section 7.1. |
|
154 type RosterItem struct { |
|
155 // Should always be "item" |
|
156 XMLName xml.Name |
|
157 Jid string `xml:"attr"` |
|
158 Subscription string `xml:"attr"` |
|
159 Name string `xml:"attr"` |
|
160 Group []string |
|
161 } |
|
162 |
154 |
163 // Describes an XMPP stanza error. See RFC 3920, Section 9.3. |
155 // Describes an XMPP stanza error. See RFC 3920, Section 9.3. |
164 type Error struct { |
156 type Error struct { |
165 // The error type attribute. |
157 // The error type attribute. |
166 Type string `xml:"attr"` |
158 Type string `xml:"attr"` |
280 return fmt.Sprintf("<%s %s>%s%s</%s %s>", u.XMLName.Space, |
272 return fmt.Sprintf("<%s %s>%s%s</%s %s>", u.XMLName.Space, |
281 u.XMLName.Local, sub, u.Chardata, u.XMLName.Space, |
273 u.XMLName.Local, sub, u.Chardata, u.XMLName.Space, |
282 u.XMLName.Local) |
274 u.XMLName.Local) |
283 } |
275 } |
284 |
276 |
285 // BUG(cjyar) This is fragile. We should find a way to use go's native |
|
286 // XML marshaling. |
|
287 func marshalXML(st Stanza) ([]byte, os.Error) { |
277 func marshalXML(st Stanza) ([]byte, os.Error) { |
288 buf := bytes.NewBuffer(nil) |
278 buf := bytes.NewBuffer(nil) |
289 buf.WriteString("<") |
279 buf.WriteString("<") |
290 buf.WriteString(st.XName()) |
280 buf.WriteString(st.XName()) |
291 if st.XTo() != "" { |
281 if st.XTo() != "" { |
302 } |
292 } |
303 if st.XLang() != "" { |
293 if st.XLang() != "" { |
304 writeField(buf, "xml:lang", st.XLang()) |
294 writeField(buf, "xml:lang", st.XLang()) |
305 } |
295 } |
306 buf.WriteString(">") |
296 buf.WriteString(">") |
307 if st.XError() != nil { |
297 if ext, ok := st.(ExtendedStanza) ; ok { |
308 bytes, _ := st.XError().MarshalXML() |
298 if st.XError() != nil { |
309 buf.WriteString(string(bytes)) |
299 bytes, _ := st.XError().MarshalXML() |
310 } |
300 buf.WriteString(string(bytes)) |
311 if st.XChild() != nil { |
301 } |
312 xml.Marshal(buf, st.XChild()) |
302 err := ext.InnerMarshal(buf) |
313 } |
303 if err != nil { |
314 if iq, ok := st.(*Iq) ; ok && iq.Query != nil { |
304 return nil, err |
315 xml.Marshal(buf, iq.Query) |
305 } |
|
306 } else { |
|
307 inner := st.innerxml() |
|
308 if inner == "" { |
|
309 xml.Marshal(buf, st.XChild()) |
|
310 } else { |
|
311 buf.WriteString(st.innerxml()) |
|
312 } |
316 } |
313 } |
317 buf.WriteString("</") |
314 buf.WriteString("</") |
318 buf.WriteString(st.XName()) |
315 buf.WriteString(st.XName()) |
319 buf.WriteString(">") |
316 buf.WriteString(">") |
320 return buf.Bytes(), nil |
317 return buf.Bytes(), nil |
367 |
364 |
368 func (m *Message) XChild() *Generic { |
365 func (m *Message) XChild() *Generic { |
369 return m.Any |
366 return m.Any |
370 } |
367 } |
371 |
368 |
|
369 func (m *Message) innerxml() string { |
|
370 return m.Innerxml |
|
371 } |
|
372 |
372 func (m *Message) MarshalXML() ([]byte, os.Error) { |
373 func (m *Message) MarshalXML() ([]byte, os.Error) { |
373 return marshalXML(m) |
374 return marshalXML(m) |
374 } |
375 } |
375 |
376 |
|
377 func (m *Message) InnerMarshal(w io.Writer) os.Error { |
|
378 err := xml.Marshal(w, m.Subject) |
|
379 if err != nil { |
|
380 return err |
|
381 } |
|
382 err = xml.Marshal(w, m.Body) |
|
383 if err != nil { |
|
384 return err |
|
385 } |
|
386 err = xml.Marshal(w, m.Thread) |
|
387 if err != nil { |
|
388 return err |
|
389 } |
|
390 return nil |
|
391 } |
|
392 |
376 func (p *Presence) XName() string { |
393 func (p *Presence) XName() string { |
377 return "presence" |
394 return "presence" |
378 } |
395 } |
379 |
396 |
380 func (p *Presence) XTo() string { |
397 func (p *Presence) XTo() string { |
403 |
420 |
404 func (p *Presence) XChild() *Generic { |
421 func (p *Presence) XChild() *Generic { |
405 return p.Any |
422 return p.Any |
406 } |
423 } |
407 |
424 |
|
425 func (p *Presence) innerxml() string { |
|
426 return p.Innerxml |
|
427 } |
|
428 |
408 func (p *Presence) MarshalXML() ([]byte, os.Error) { |
429 func (p *Presence) MarshalXML() ([]byte, os.Error) { |
409 return marshalXML(p) |
430 return marshalXML(p) |
410 } |
431 } |
411 |
432 |
|
433 func (p *Presence) InnerMarshal(w io.Writer) os.Error { |
|
434 err := xml.Marshal(w, p.Show) |
|
435 if err != nil { |
|
436 return err |
|
437 } |
|
438 err = xml.Marshal(w, p.Status) |
|
439 if err != nil { |
|
440 return err |
|
441 } |
|
442 err = xml.Marshal(w, p.Priority) |
|
443 if err != nil { |
|
444 return err |
|
445 } |
|
446 return nil |
|
447 } |
|
448 |
412 func (iq *Iq) XName() string { |
449 func (iq *Iq) XName() string { |
413 return "iq" |
450 return "iq" |
414 } |
451 } |
415 |
452 |
416 func (iq *Iq) XTo() string { |
453 func (iq *Iq) XTo() string { |