|
1 // Copyright 2011 The Go Authors. All rights reserved. |
|
2 // Use of this source code is governed by a BSD-style |
|
3 // license that can be found in the LICENSE file. |
|
4 |
|
5 package xmpp |
|
6 |
|
7 // This file contains data structures. |
|
8 |
|
9 import ( |
|
10 "bytes" |
|
11 "fmt" |
|
12 "io" |
|
13 "os" |
|
14 "xml" |
|
15 ) |
|
16 |
|
17 const ( |
|
18 // Version of RFC 3920 that we implement. |
|
19 Version = "1.0" |
|
20 nsStreams = "urn:ietf:params:xml:ns:xmpp-streams" |
|
21 nsStream = "http://etherx.jabber.org/streams" |
|
22 nsTLS = "urn:ietf:params:xml:ns:xmpp-tls" |
|
23 ) |
|
24 |
|
25 // JID represents an entity that can communicate with other |
|
26 // entities. It looks like node@domain/resource. Node and resource are |
|
27 // sometimes optional. |
|
28 type JID struct { |
|
29 Node *string |
|
30 Domain string |
|
31 Resource *string |
|
32 } |
|
33 var _ fmt.Stringer = &JID{} |
|
34 |
|
35 // XMPP's <stream:stream> XML element |
|
36 type Stream struct { |
|
37 to string `xml:"attr"` |
|
38 from string `xml:"attr"` |
|
39 id string `xml:"attr"` |
|
40 lang string `xml:"attr"` |
|
41 version string `xml:"attr"` |
|
42 } |
|
43 var _ xml.Marshaler = &Stream{} |
|
44 |
|
45 type StreamError struct { |
|
46 cond definedCondition |
|
47 text errText |
|
48 } |
|
49 var _ xml.Marshaler = &StreamError{} |
|
50 |
|
51 type definedCondition struct { |
|
52 // Must always be in namespace nsStreams |
|
53 XMLName xml.Name |
|
54 } |
|
55 |
|
56 type errText struct { |
|
57 XMLName xml.Name |
|
58 Lang string |
|
59 text string `xml:"chardata"` |
|
60 } |
|
61 var _ xml.Marshaler = &errText{} |
|
62 |
|
63 func (jid *JID) String() string { |
|
64 result := jid.Domain |
|
65 if jid.Node != nil { |
|
66 result = *jid.Node + "@" + result |
|
67 } |
|
68 if jid.Resource != nil { |
|
69 result = result + "/" + *jid.Resource |
|
70 } |
|
71 return result |
|
72 } |
|
73 |
|
74 func (s *Stream) MarshalXML() ([]byte, os.Error) { |
|
75 buf := bytes.NewBuffer(nil) |
|
76 buf.WriteString("<stream:stream") |
|
77 writeField(buf, "to", s.to) |
|
78 writeField(buf, "from", s.from) |
|
79 writeField(buf, "id", s.id) |
|
80 writeField(buf, "xml:lang", s.lang) |
|
81 writeField(buf, "version", s.version) |
|
82 buf.WriteString(">") |
|
83 // We never write </stream:stream> |
|
84 return buf.Bytes(), nil |
|
85 } |
|
86 |
|
87 func (s *StreamError) MarshalXML() ([]byte, os.Error) { |
|
88 buf := bytes.NewBuffer(nil) |
|
89 buf.WriteString("<stream:error>") |
|
90 xml.Marshal(buf, s.cond) |
|
91 xml.Marshal(buf, s.text) |
|
92 buf.WriteString("</stream:error>") |
|
93 return buf.Bytes(), nil |
|
94 } |
|
95 |
|
96 func (e *errText) MarshalXML() ([]byte, os.Error) { |
|
97 buf := bytes.NewBuffer(nil) |
|
98 buf.WriteString("<text") |
|
99 writeField(buf, "xmlns", nsStreams) |
|
100 writeField(buf, "xml:lang", e.Lang) |
|
101 buf.WriteString(">") |
|
102 xml.Escape(buf, []byte(e.text)) |
|
103 buf.WriteString("</text>") |
|
104 return buf.Bytes(), nil |
|
105 } |
|
106 |
|
107 func writeField(w io.Writer, field, value string) { |
|
108 if value != "" { |
|
109 io.WriteString(w, " ") |
|
110 io.WriteString(w, field) |
|
111 io.WriteString(w, `="`) |
|
112 xml.Escape(w, []byte(value)) |
|
113 io.WriteString(w, `"`) |
|
114 } |
|
115 } |