78 Any *Generic |
77 Any *Generic |
79 } |
78 } |
80 |
79 |
81 // One of the three core XMPP stanza types: iq, message, presence. See |
80 // One of the three core XMPP stanza types: iq, message, presence. See |
82 // RFC3920, section 9. |
81 // RFC3920, section 9. |
83 type Stanza interface { |
82 type Stanza struct { |
84 // // Returns "iq", "message", or "presence". |
|
85 // GetName() string |
|
86 // // The to attribute. |
|
87 // GetTo() string |
|
88 // // The from attribute. |
|
89 // GetFrom() string |
|
90 // The id attribute. TODO maybe remove this. |
|
91 GetId() string |
|
92 // // The type attribute. |
|
93 // GetType() string |
|
94 // // The xml:lang attribute. |
|
95 // GetLang() string |
|
96 // // A nested error element, if any. |
|
97 // GetError() *Error |
|
98 // // Zero or more (non-error) nested elements. These will be in |
|
99 // // namespaces managed by extensions. |
|
100 // GetNested() []interface{} |
|
101 addNested(interface{}) |
|
102 innerxml() string |
|
103 } |
|
104 |
|
105 // message stanza |
|
106 type Message struct { |
|
107 XMLName xml.Name `xml:"message"` |
|
108 To string `xml:"to,attr,omitempty"` |
|
109 From string `xml:"from,attr,omitempty"` |
|
110 Id string `xml:"id,attr,omitempty"` |
|
111 Type string `xml:"type,attr,omitempty"` |
|
112 Lang string `xml:"http://www.w3.org/XML/1998/namespace lang,attr,omitempty"` |
|
113 Innerxml string `xml:",innerxml"` |
|
114 Error *Error |
|
115 Subject *Generic `xml:"subject"` |
|
116 Body *Generic `xml:"body"` |
|
117 Thread *Generic `xml:"thread"` |
|
118 Nested []interface{} |
|
119 } |
|
120 var _ Stanza = &Message{} |
|
121 |
|
122 // presence stanza |
|
123 type Presence struct { |
|
124 XMLName xml.Name `xml:"presence"` |
|
125 To string `xml:"to,attr,omitempty"` |
|
126 From string `xml:"from,attr,omitempty"` |
|
127 Id string `xml:"id,attr,omitempty"` |
|
128 Type string `xml:"type,attr,omitempty"` |
|
129 Lang string `xml:"http://www.w3.org/XML/1998/namespace lang,attr,omitempty"` |
|
130 Innerxml string `xml:",innerxml"` |
|
131 Error *Error |
|
132 Show *Generic `xml:"show"` |
|
133 Status *Generic `xml:"status"` |
|
134 Priority *Generic `xml:"priority"` |
|
135 Nested []interface{} |
|
136 } |
|
137 var _ Stanza = &Presence{} |
|
138 |
|
139 // iq stanza |
|
140 type Iq struct { |
|
141 XMLName xml.Name `xml:"iq"` |
|
142 To string `xml:"to,attr,omitempty"` |
83 To string `xml:"to,attr,omitempty"` |
143 From string `xml:"from,attr,omitempty"` |
84 From string `xml:"from,attr,omitempty"` |
144 Id string `xml:"id,attr,omitempty"` |
85 Id string `xml:"id,attr,omitempty"` |
145 Type string `xml:"type,attr,omitempty"` |
86 Type string `xml:"type,attr,omitempty"` |
146 Lang string `xml:"http://www.w3.org/XML/1998/namespace lang,attr,omitempty"` |
87 Lang string `xml:"http://www.w3.org/XML/1998/namespace lang,attr,omitempty"` |
147 Innerxml string `xml:",innerxml"` |
88 Innerxml string `xml:",innerxml"` |
148 Error *Error |
89 Error *Error |
149 Nested []interface{} |
90 Nested []interface{} |
150 } |
91 } |
151 var _ Stanza = &Iq{} |
92 |
|
93 // message stanza |
|
94 type Message struct { |
|
95 XMLName xml.Name `xml:"message"` |
|
96 Stanza |
|
97 Subject *Generic `xml:"subject"` |
|
98 Body *Generic `xml:"body"` |
|
99 Thread *Generic `xml:"thread"` |
|
100 } |
|
101 |
|
102 // presence stanza |
|
103 type Presence struct { |
|
104 XMLName xml.Name `xml:"presence"` |
|
105 Stanza |
|
106 Show *Generic `xml:"show"` |
|
107 Status *Generic `xml:"status"` |
|
108 Priority *Generic `xml:"priority"` |
|
109 } |
|
110 |
|
111 // iq stanza |
|
112 type Iq struct { |
|
113 XMLName xml.Name `xml:"iq"` |
|
114 Stanza |
|
115 } |
152 |
116 |
153 // Describes an XMPP stanza error. See RFC 3920, Section 9.3. |
117 // Describes an XMPP stanza error. See RFC 3920, Section 9.3. |
154 type Error struct { |
118 type Error struct { |
155 XMLName xml.Name `xml:"error"` |
119 XMLName xml.Name `xml:"error"` |
156 // The error type attribute. |
120 // The error type attribute. |
278 return "unreadable error" |
242 return "unreadable error" |
279 } |
243 } |
280 return string(buf) |
244 return string(buf) |
281 } |
245 } |
282 |
246 |
283 func (m *Message) GetId() string { |
|
284 return m.Id |
|
285 } |
|
286 |
|
287 func (m *Message) addNested(n interface{}) { |
|
288 m.Nested = append(m.Nested, n) |
|
289 } |
|
290 |
|
291 func (m *Message) innerxml() string { |
|
292 return m.Innerxml |
|
293 } |
|
294 |
|
295 func (p *Presence) GetId() string { |
|
296 return p.Id |
|
297 } |
|
298 |
|
299 func (p *Presence) addNested(n interface{}) { |
|
300 p.Nested = append(p.Nested, n) |
|
301 } |
|
302 |
|
303 func (p *Presence) innerxml() string { |
|
304 return p.Innerxml |
|
305 } |
|
306 |
|
307 func (iq *Iq) GetId() string { |
|
308 return iq.Id |
|
309 } |
|
310 |
|
311 func (iq *Iq) addNested(n interface{}) { |
|
312 iq.Nested = append(iq.Nested, n) |
|
313 } |
|
314 |
|
315 func (iq *Iq) innerxml() string { |
|
316 return iq.Innerxml |
|
317 } |
|
318 |
|
319 |
|
320 // Parse a string into a struct implementing Stanza -- this will be |
|
321 // either an Iq, a Message, or a Presence. |
|
322 func ParseStanza(str string) (Stanza, error) { |
|
323 r := strings.NewReader(str) |
|
324 p := xml.NewDecoder(r) |
|
325 tok, err := p.Token() |
|
326 if err != nil { |
|
327 return nil, err |
|
328 } |
|
329 se, ok := tok.(xml.StartElement) |
|
330 if !ok { |
|
331 return nil, errors.New("Not a start element") |
|
332 } |
|
333 var stan Stanza |
|
334 switch se.Name.Local { |
|
335 case "iq": |
|
336 stan = &Iq{} |
|
337 case "message": |
|
338 stan = &Message{} |
|
339 case "presence": |
|
340 stan = &Presence{} |
|
341 default: |
|
342 return nil, errors.New("Not iq, message, or presence") |
|
343 } |
|
344 err = p.DecodeElement(stan, &se) |
|
345 if err != nil { |
|
346 return nil, err |
|
347 } |
|
348 return stan, nil |
|
349 } |
|
350 |
|
351 var bindExt Extension = Extension{StanzaHandlers: map[string]func(*xml.Name) interface{}{NsBind: newBind}, |
247 var bindExt Extension = Extension{StanzaHandlers: map[string]func(*xml.Name) interface{}{NsBind: newBind}, |
352 Start: func(cl *Client) {}} |
248 Start: func(cl *Client) {}} |
353 |
249 |
354 func newBind(name *xml.Name) interface{} { |
250 func newBind(name *xml.Name) interface{} { |
355 return &bindIq{} |
251 return &bindIq{} |
356 } |
252 } |
|
253 |
|
254 func getStanza(v interface{}) *Stanza { |
|
255 switch s := v.(type) { |
|
256 case *Iq: |
|
257 return &s.Stanza |
|
258 case *Message: |
|
259 return &s.Stanza |
|
260 case *Presence: |
|
261 return &s.Stanza |
|
262 } |
|
263 return nil |
|
264 } |