1extern crate minidom;
2
3use minidom::Element;
4
5use error::Error;
6
7use disco::{Feature, Identity, Disco, parse_disco};
8use data_forms::DataForm;
9
10fn compute_item(field: String) -> Vec<u8> {
11 let mut bytes = field.as_bytes().to_vec();
12 bytes.push(0x1f);
13 bytes
14}
15
16fn compute_items<T, F: Fn(T) -> Vec<u8>>(things: Vec<T>, separator: u8, encode: F) -> Vec<u8> {
17 let mut string: Vec<u8> = vec!();
18 let mut accumulator: Vec<Vec<u8>> = vec!();
19 for thing in things {
20 let bytes = encode(thing);
21 accumulator.push(bytes);
22 }
23 // This works using the expected i;octet collation.
24 accumulator.sort();
25 for mut bytes in accumulator {
26 string.append(&mut bytes);
27 }
28 string.push(separator);
29 string
30}
31
32fn compute_features(features: Vec<Feature>) -> Vec<u8> {
33 compute_items(features, 0x1c, |feature| compute_item(feature.var))
34}
35
36fn compute_identities(identities: Vec<Identity>) -> Vec<u8> {
37 compute_items(identities, 0x1c, |identity| {
38 let mut bytes = compute_item(identity.category);
39 bytes.append(&mut compute_item(identity.type_));
40 bytes.append(&mut compute_item(identity.xml_lang));
41 bytes.append(&mut compute_item(identity.name.unwrap_or(String::new())));
42 bytes.push(0x1e);
43 bytes
44 })
45}
46
47fn compute_extensions(extensions: Vec<DataForm>) -> Vec<u8> {
48 compute_items(extensions, 0x1c, |extension| {
49 compute_items(extension.fields, 0x1d, |field| {
50 let mut bytes = compute_item(field.var);
51 bytes.append(&mut compute_items(field.values, 0x1e,
52 |value| compute_item(value)));
53 bytes
54 })
55 })
56}
57
58fn compute_disco(disco: Disco) -> Vec<u8> {
59 let features_string = compute_features(disco.features);
60 let identities_string = compute_identities(disco.identities);
61 let extensions_string = compute_extensions(disco.extensions);
62
63 let mut final_string = vec!();
64 final_string.extend(features_string);
65 final_string.extend(identities_string);
66 final_string.extend(extensions_string);
67 final_string
68}
69
70pub fn convert_element(root: &Element) -> Result<Vec<u8>, Error> {
71 let disco = parse_disco(root)?;
72 let final_string = compute_disco(disco);
73 Ok(final_string)
74}
75
76#[cfg(test)]
77mod tests {
78 use minidom::Element;
79 use ecaps2;
80
81 #[test]
82 fn test_simple() {
83 let elem: Element = "<query xmlns='http://jabber.org/protocol/disco#info'><identity category='client' type='pc'/><feature var='http://jabber.org/protocol/disco#info'/></query>".parse().unwrap();
84 let ecaps2 = ecaps2::convert_element(&elem).unwrap();
85 assert_eq!(ecaps2.len(), 54);
86 }
87
88 #[test]
89 fn test_xep_ex1() {
90 let elem: Element = r#"
91<query xmlns="http://jabber.org/protocol/disco#info">
92 <identity category="client" name="BombusMod" type="mobile"/>
93 <feature var="http://jabber.org/protocol/si"/>
94 <feature var="http://jabber.org/protocol/bytestreams"/>
95 <feature var="http://jabber.org/protocol/chatstates"/>
96 <feature var="http://jabber.org/protocol/disco#info"/>
97 <feature var="http://jabber.org/protocol/disco#items"/>
98 <feature var="urn:xmpp:ping"/>
99 <feature var="jabber:iq:time"/>
100 <feature var="jabber:iq:privacy"/>
101 <feature var="jabber:iq:version"/>
102 <feature var="http://jabber.org/protocol/rosterx"/>
103 <feature var="urn:xmpp:time"/>
104 <feature var="jabber:x:oob"/>
105 <feature var="http://jabber.org/protocol/ibb"/>
106 <feature var="http://jabber.org/protocol/si/profile/file-transfer"/>
107 <feature var="urn:xmpp:receipts"/>
108 <feature var="jabber:iq:roster"/>
109 <feature var="jabber:iq:last"/>
110</query>
111"#.parse().unwrap();
112 let expected = vec![104, 116, 116, 112, 58, 47, 47, 106, 97, 98, 98,
113 101, 114, 46, 111, 114, 103, 47, 112, 114, 111, 116, 111, 99, 111,
114 108, 47, 98, 121, 116, 101, 115, 116, 114, 101, 97, 109, 115, 31,
115 104, 116, 116, 112, 58, 47, 47, 106, 97, 98, 98, 101, 114, 46, 111,
116 114, 103, 47, 112, 114, 111, 116, 111, 99, 111, 108, 47, 99, 104,
117 97, 116, 115, 116, 97, 116, 101, 115, 31, 104, 116, 116, 112, 58,
118 47, 47, 106, 97, 98, 98, 101, 114, 46, 111, 114, 103, 47, 112, 114,
119 111, 116, 111, 99, 111, 108, 47, 100, 105, 115, 99, 111, 35, 105,
120 110, 102, 111, 31, 104, 116, 116, 112, 58, 47, 47, 106, 97, 98, 98,
121 101, 114, 46, 111, 114, 103, 47, 112, 114, 111, 116, 111, 99, 111,
122 108, 47, 100, 105, 115, 99, 111, 35, 105, 116, 101, 109, 115, 31,
123 104, 116, 116, 112, 58, 47, 47, 106, 97, 98, 98, 101, 114, 46, 111,
124 114, 103, 47, 112, 114, 111, 116, 111, 99, 111, 108, 47, 105, 98,
125 98, 31, 104, 116, 116, 112, 58, 47, 47, 106, 97, 98, 98, 101, 114,
126 46, 111, 114, 103, 47, 112, 114, 111, 116, 111, 99, 111, 108, 47,
127 114, 111, 115, 116, 101, 114, 120, 31, 104, 116, 116, 112, 58, 47,
128 47, 106, 97, 98, 98, 101, 114, 46, 111, 114, 103, 47, 112, 114,
129 111, 116, 111, 99, 111, 108, 47, 115, 105, 31, 104, 116, 116, 112,
130 58, 47, 47, 106, 97, 98, 98, 101, 114, 46, 111, 114, 103, 47, 112,
131 114, 111, 116, 111, 99, 111, 108, 47, 115, 105, 47, 112, 114, 111,
132 102, 105, 108, 101, 47, 102, 105, 108, 101, 45, 116, 114, 97, 110,
133 115, 102, 101, 114, 31, 106, 97, 98, 98, 101, 114, 58, 105, 113,
134 58, 108, 97, 115, 116, 31, 106, 97, 98, 98, 101, 114, 58, 105, 113,
135 58, 112, 114, 105, 118, 97, 99, 121, 31, 106, 97, 98, 98, 101, 114,
136 58, 105, 113, 58, 114, 111, 115, 116, 101, 114, 31, 106, 97, 98,
137 98, 101, 114, 58, 105, 113, 58, 116, 105, 109, 101, 31, 106, 97,
138 98, 98, 101, 114, 58, 105, 113, 58, 118, 101, 114, 115, 105, 111,
139 110, 31, 106, 97, 98, 98, 101, 114, 58, 120, 58, 111, 111, 98, 31,
140 117, 114, 110, 58, 120, 109, 112, 112, 58, 112, 105, 110, 103, 31,
141 117, 114, 110, 58, 120, 109, 112, 112, 58, 114, 101, 99, 101, 105,
142 112, 116, 115, 31, 117, 114, 110, 58, 120, 109, 112, 112, 58, 116,
143 105, 109, 101, 31, 28, 99, 108, 105, 101, 110, 116, 31, 109, 111,
144 98, 105, 108, 101, 31, 31, 66, 111, 109, 98, 117, 115, 77, 111,
145 100, 31, 30, 28, 28];
146 let ecaps2 = ecaps2::convert_element(&elem).unwrap();
147 assert_eq!(ecaps2.len(), 0x1d9);
148 assert_eq!(ecaps2, expected);
149
150 /*
151 let sha_256 = hash(ecaps2, "sha-256");
152 assert_eq!(sha_256, "kzBZbkqJ3ADrj7v08reD1qcWUwNGHaidNUgD7nHpiw8=");
153 let sha3_256 = hash(ecaps2, "sha3-256");
154 assert_eq!(sha3_256, "79mdYAfU9rEdTOcWDO7UEAt6E56SUzk/g6TnqUeuD9Q=");
155 */
156 }
157
158 #[test]
159 fn test_xep_ex2() {
160 let elem: Element = r#"
161<query xmlns="http://jabber.org/protocol/disco#info">
162 <identity category="client" name="Tkabber" type="pc" xml:lang="en"/>
163 <identity category="client" name="Ткаббер" type="pc" xml:lang="ru"/>
164 <feature var="games:board"/>
165 <feature var="http://jabber.org/protocol/activity"/>
166 <feature var="http://jabber.org/protocol/activity+notify"/>
167 <feature var="http://jabber.org/protocol/bytestreams"/>
168 <feature var="http://jabber.org/protocol/chatstates"/>
169 <feature var="http://jabber.org/protocol/commands"/>
170 <feature var="http://jabber.org/protocol/disco#info"/>
171 <feature var="http://jabber.org/protocol/disco#items"/>
172 <feature var="http://jabber.org/protocol/evil"/>
173 <feature var="http://jabber.org/protocol/feature-neg"/>
174 <feature var="http://jabber.org/protocol/geoloc"/>
175 <feature var="http://jabber.org/protocol/geoloc+notify"/>
176 <feature var="http://jabber.org/protocol/ibb"/>
177 <feature var="http://jabber.org/protocol/iqibb"/>
178 <feature var="http://jabber.org/protocol/mood"/>
179 <feature var="http://jabber.org/protocol/mood+notify"/>
180 <feature var="http://jabber.org/protocol/rosterx"/>
181 <feature var="http://jabber.org/protocol/si"/>
182 <feature var="http://jabber.org/protocol/si/profile/file-transfer"/>
183 <feature var="http://jabber.org/protocol/tune"/>
184 <feature var="http://www.facebook.com/xmpp/messages"/>
185 <feature var="http://www.xmpp.org/extensions/xep-0084.html#ns-metadata+notify"/>
186 <feature var="jabber:iq:avatar"/>
187 <feature var="jabber:iq:browse"/>
188 <feature var="jabber:iq:dtcp"/>
189 <feature var="jabber:iq:filexfer"/>
190 <feature var="jabber:iq:ibb"/>
191 <feature var="jabber:iq:inband"/>
192 <feature var="jabber:iq:jidlink"/>
193 <feature var="jabber:iq:last"/>
194 <feature var="jabber:iq:oob"/>
195 <feature var="jabber:iq:privacy"/>
196 <feature var="jabber:iq:roster"/>
197 <feature var="jabber:iq:time"/>
198 <feature var="jabber:iq:version"/>
199 <feature var="jabber:x:data"/>
200 <feature var="jabber:x:event"/>
201 <feature var="jabber:x:oob"/>
202 <feature var="urn:xmpp:avatar:metadata+notify"/>
203 <feature var="urn:xmpp:ping"/>
204 <feature var="urn:xmpp:receipts"/>
205 <feature var="urn:xmpp:time"/>
206 <x xmlns="jabber:x:data" type="result">
207 <field type="hidden" var="FORM_TYPE">
208 <value>urn:xmpp:dataforms:softwareinfo</value>
209 </field>
210 <field var="software">
211 <value>Tkabber</value>
212 </field>
213 <field var="software_version">
214 <value>0.11.1-svn-20111216-mod (Tcl/Tk 8.6b2)</value>
215 </field>
216 <field var="os">
217 <value>Windows</value>
218 </field>
219 <field var="os_version">
220 <value>XP</value>
221 </field>
222 </x>
223</query>
224"#.parse().unwrap();
225 let expected = vec![103, 97, 109, 101, 115, 58, 98, 111, 97, 114, 100,
226 31, 104, 116, 116, 112, 58, 47, 47, 106, 97, 98, 98, 101, 114, 46,
227 111, 114, 103, 47, 112, 114, 111, 116, 111, 99, 111, 108, 47, 97,
228 99, 116, 105, 118, 105, 116, 121, 31, 104, 116, 116, 112, 58, 47,
229 47, 106, 97, 98, 98, 101, 114, 46, 111, 114, 103, 47, 112, 114,
230 111, 116, 111, 99, 111, 108, 47, 97, 99, 116, 105, 118, 105, 116,
231 121, 43, 110, 111, 116, 105, 102, 121, 31, 104, 116, 116, 112, 58,
232 47, 47, 106, 97, 98, 98, 101, 114, 46, 111, 114, 103, 47, 112, 114,
233 111, 116, 111, 99, 111, 108, 47, 98, 121, 116, 101, 115, 116, 114,
234 101, 97, 109, 115, 31, 104, 116, 116, 112, 58,47, 47, 106, 97, 98,
235 98, 101, 114, 46, 111, 114, 103, 47, 112, 114, 111, 116, 111, 99,
236 111, 108, 47, 99, 104, 97, 116, 115, 116, 97, 116, 101, 115, 31,
237 104, 116, 116, 112, 58, 47, 47, 106, 97, 98, 98, 101, 114, 46, 111,
238 114, 103, 47, 112, 114, 111, 116, 111, 99, 111, 108, 47, 99, 111,
239 109, 109, 97, 110, 100, 115, 31,104,116, 116, 112, 58, 47, 47, 106,
240 97, 98, 98, 101, 114, 46, 111, 114, 103, 47, 112, 114, 111, 116,
241 111, 99, 111, 108, 47, 100, 105, 115, 99, 111, 35, 105, 110, 102,
242 111, 31, 104, 116, 116, 112, 58, 47, 47, 106, 97, 98, 98, 101, 114,
243 46, 111, 114, 103, 47, 112, 114, 111, 116, 111, 99, 111, 108, 47,
244 100, 105, 115, 99, 111, 35, 105, 116, 101, 109, 115, 31, 104, 116,
245 116, 112, 58, 47, 47, 106, 97, 98, 98, 101, 114, 46, 111, 114, 103,
246 47, 112, 114, 111, 116, 111, 99, 111, 108, 47, 101, 118, 105, 108,
247 31, 104, 116, 116, 112, 58, 47, 47, 106, 97, 98, 98, 101, 114, 46,
248 111, 114, 103, 47, 112, 114, 111, 116, 111, 99, 111, 108, 47, 102,
249 101, 97, 116, 117, 114, 101, 45, 110, 101, 103, 31, 104, 116, 116,
250 112, 58, 47, 47, 106, 97, 98, 98, 101, 114, 46, 111, 114, 103, 47,
251 112, 114, 111, 116, 111, 99, 111, 108, 47, 103, 101, 111, 108, 111,
252 99, 31, 104, 116, 116, 112, 58, 47, 47, 106, 97, 98, 98, 101, 114,
253 46, 111, 114, 103, 47, 112, 114, 111, 116, 111, 99,111, 108, 47,
254 103, 101, 111, 108, 111, 99, 43, 110, 111, 116, 105, 102, 121, 31,
255 104, 116, 116, 112, 58, 47, 47, 106, 97, 98, 98, 101, 114, 46, 111,
256 114, 103,47, 112, 114, 111, 116, 111, 99, 111, 108, 47, 105, 98,
257 98, 31, 104, 116, 116, 112, 58, 47, 47, 106, 97, 98, 98, 101, 114,
258 46, 111, 114, 103, 47, 112, 114, 111,116, 111, 99, 111, 108, 47,
259 105, 113, 105, 98, 98, 31, 104, 116, 116, 112, 58, 47, 47, 106, 97,
260 98, 98, 101, 114, 46, 111, 114, 103, 47, 112, 114, 111, 116,111,
261 99, 111, 108, 47, 109, 111, 111, 100, 31, 104, 116, 116, 112, 58,
262 47, 47, 106, 97, 98, 98, 101, 114, 46, 111, 114, 103, 47, 112, 114,
263 111, 116, 111, 99, 111,108, 47, 109, 111, 111, 100, 43, 110, 111,
264 116, 105, 102, 121, 31, 104, 116, 116, 112, 58, 47, 47, 106, 97,
265 98, 98, 101, 114, 46, 111, 114, 103, 47, 112, 114, 111, 116, 111,
266 99, 111, 108, 47, 114, 111, 115, 116, 101, 114, 120, 31, 104, 116,
267 116, 112, 58, 47, 47, 106, 97, 98, 98, 101, 114, 46, 111, 114, 103,
268 47, 112, 114, 111, 116, 111, 99, 111, 108, 47, 115, 105, 31, 104,
269 116, 116, 112, 58, 47, 47, 106, 97, 98, 98, 101, 114, 46, 111, 114,
270 103, 47, 112, 114, 111, 116, 111, 99, 111, 108, 47, 115, 105, 47,
271 112, 114, 111, 102, 105, 108, 101, 47, 102, 105, 108, 101, 45, 116,
272 114, 97, 110, 115, 102, 101, 114, 31, 104, 116, 116, 112, 58, 47,
273 47, 106, 97, 98, 98, 101, 114, 46, 111, 114, 103, 47, 112, 114,
274 111, 116, 111, 99, 111, 108, 47, 116, 117, 110, 101, 31, 104, 116,
275 116, 112, 58, 47, 47, 119, 119, 119, 46, 102, 97, 99, 101, 98, 111,
276 111, 107, 46, 99, 111, 109, 47, 120, 109, 112, 112, 47, 109, 101,
277 115, 115, 97, 103, 101, 115, 31, 104, 116, 116, 112, 58, 47, 47,
278 119, 119, 119, 46, 120, 109, 112, 112, 46, 111, 114, 103, 47, 101,
279 120, 116, 101, 110, 115, 105, 111, 110, 115, 47, 120, 101, 112, 45,
280 48, 48, 56, 52, 46, 104, 116, 109, 108, 35, 110, 115, 45, 109, 101,
281 116, 97, 100, 97, 116, 97, 43, 110, 111, 116, 105, 102, 121, 31,
282 106, 97, 98, 98, 101, 114,58, 105,113, 58, 97, 118, 97, 116, 97,
283 114, 31, 106, 97, 98, 98, 101, 114, 58, 105, 113, 58, 98, 114, 111,
284 119, 115, 101, 31, 106, 97, 98, 98, 101, 114, 58, 105, 113, 58,
285 100, 116, 99, 112, 31, 106, 97, 98, 98, 101, 114, 58, 105, 113, 58,
286 102, 105, 108, 101, 120, 102, 101, 114, 31, 106, 97, 98, 98, 101,
287 114, 58, 105, 113, 58, 105, 98, 98, 31, 106, 97, 98, 98, 101, 114,
288 58, 105, 113, 58, 105, 110, 98, 97, 110, 100, 31, 106, 97, 98, 98,
289 101, 114, 58, 105, 113, 58, 106, 105, 100, 108, 105, 110, 107, 31,
290 106, 97, 98, 98, 101, 114, 58, 105, 113, 58, 108, 97, 115, 116, 31,
291 106, 97, 98, 98, 101, 114, 58, 105, 113, 58, 111, 111, 98, 31, 106,
292 97,98, 98, 101, 114, 58, 105, 113, 58, 112, 114, 105, 118, 97, 99,
293 121, 31, 106, 97, 98, 98, 101, 114, 58, 105, 113, 58, 114, 111,
294 115, 116, 101, 114,31, 106, 97, 98, 98, 101, 114, 58, 105, 113, 58,
295 116, 105, 109, 101, 31, 106, 97, 98, 98, 101, 114, 58, 105, 113,
296 58, 118, 101, 114, 115, 105, 111, 110, 31, 106, 97, 98, 98, 101,
297 114, 58, 120, 58, 100, 97, 116, 97, 31, 106, 97, 98, 98, 101, 114,
298 58, 120, 58, 101, 118, 101, 110, 116, 31, 106, 97, 98, 98, 101,
299 114, 58, 120, 58, 111, 111, 98, 31, 117, 114, 110, 58, 120, 109,
300 112, 112, 58, 97, 118, 97, 116, 97, 114, 58, 109, 101, 116, 97,
301 100, 97, 116, 97, 43, 110, 111, 116, 105, 102, 121,31, 117, 114,
302 110, 58, 120, 109, 112, 112, 58, 112, 105, 110, 103, 31, 117, 114,
303 110, 58, 120, 109, 112, 112, 58, 114, 101, 99, 101, 105, 112, 116,
304 115, 31, 117, 114, 110, 58, 120, 109, 112, 112, 58, 116, 105, 109,
305 101, 31, 28, 99, 108, 105, 101, 110, 116, 31, 112, 99, 31, 101,
306 110, 31, 84, 107, 97, 98, 98, 101, 114,31, 30, 99, 108, 105, 101,
307 110, 116, 31, 112, 99, 31, 114, 117, 31, 208, 162, 208, 186, 208,
308 176, 208, 177, 208, 177, 208, 181, 209, 128, 31, 30, 28, 70, 79,
309 82, 77, 95, 84, 89, 80, 69, 31, 117, 114, 110, 58, 120, 109, 112,
310 112, 58, 100, 97, 116, 97, 102, 111, 114, 109, 115, 58, 115, 111,
311 102, 116, 119, 97, 114, 101,105, 110, 102, 111, 31, 30, 111, 115,
312 31, 87, 105, 110, 100, 111, 119, 115, 31, 30, 111, 115, 95, 118,
313 101, 114, 115, 105, 111, 110, 31, 88, 80, 31, 30, 115, 111, 102,
314 116, 119, 97, 114, 101, 31, 84, 107, 97, 98, 98, 101, 114, 31, 30,
315 115, 111, 102, 116, 119, 97, 114, 101, 95, 118, 101, 114, 115, 105,
316 111, 110, 31, 48, 46, 49, 49, 46, 49, 45, 115, 118, 110, 45, 50,
317 48, 49, 49, 49, 50, 49, 54, 45, 109, 111, 100, 32, 40, 84, 99, 108,
318 47, 84, 107, 32, 56, 46,54, 98, 50, 41, 31, 30, 29, 28];
319 let ecaps2 = ecaps2::convert_element(&elem).unwrap();
320 assert_eq!(ecaps2.len(), 0x543);
321 assert_eq!(ecaps2, expected);
322
323 /*
324 let sha_256 = hash(ecaps2, "sha-256");
325 assert_eq!(sha_256, "u79ZroNJbdSWhdSp311mddz44oHHPsEBntQ5b1jqBSY=");
326 let sha3_256 = hash(ecaps2, "sha3-256");
327 assert_eq!(sha3_256, "XpUJzLAc93258sMECZ3FJpebkzuyNXDzRNwQog8eycg=");
328 */
329 }
330}