From Mariusz Okrój and Sebastien Vincent via https://bugs.wireshark.org/bugzilla...
[obnox/wireshark/wip.git] / epan / dissectors / packet-xmpp-other.c
1 /* xmpp-other.c
2  * Wireshark's XMPP dissector.
3  *
4  * Copyright 2011, Mariusz Okroj <okrojmariusz[]gmail.com>
5  *
6  * $Id$
7  *
8  * Wireshark - Network traffic analyzer
9  * By Gerald Combs <gerald@wireshark.org>
10  * Copyright 1998 Gerald Combs
11  *
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public License
14  * as published by the Free Software Foundation; either version 2
15  * of the License, or (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
25  */
26
27 #ifdef HAVE_CONFIG_H
28 #include "config.h"
29 #endif
30
31 #include<stdio.h>
32 #include<string.h>
33 #include <glib.h>
34
35 #include <epan/packet.h>
36 #include <epan/proto.h>
37 #include <epan/tvbuff.h>
38 #include <epan/emem.h>
39 #include <epan/conversation.h>
40 #include <epan/strutil.h>
41 #include <epan/expert.h>
42
43 #include <epan/dissectors/packet-xml.h>
44
45 #include <packet-xmpp-utils.h>
46 #include <packet-xmpp.h>
47 #include <packet-xmpp-jingle.h>
48 #include <packet-xmpp-other.h>
49
50 static void xmpp_disco_items_item(proto_tree *tree, tvbuff_t *tvb, packet_info* pinfo, element_t *element);
51
52 static void xmpp_roster_item(proto_tree *tree, tvbuff_t *tvb, packet_info* pinfo, element_t *element);
53
54 static void xmpp_disco_info_identity(proto_tree *tree, tvbuff_t *tvb, packet_info* pinfo, element_t *element);
55 static void xmpp_disco_info_feature(proto_tree *tree, tvbuff_t *tvb, element_t *element);
56
57 static void xmpp_bytestreams_streamhost(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element);
58 static void xmpp_bytestreams_streamhost_used(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element);
59 static void xmpp_bytestreams_activate(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element);
60 static void xmpp_bytestreams_udpsuccess(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element);
61
62 static void xmpp_si_file(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element);
63 static void xmpp_si_file_range(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element);
64
65 static void xmpp_x_data_field(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element);
66 static void xmpp_x_data_field_option(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element);
67 static void xmpp_x_data_field_value(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element);
68 static void xmpp_x_data_instr(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element);
69
70 static void xmpp_muc_history(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element);
71
72 static void xmpp_muc_user_item(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element);
73 static void xmpp_muc_user_status(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element);
74 static void xmpp_muc_user_invite(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element);
75
76 static void xmpp_hashes_hash(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element);
77
78 static void xmpp_jitsi_inputevt_rmt_ctrl(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element);
79
80 void
81 xmpp_iq_bind(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element)
82 {
83     proto_item *bind_item;
84     proto_tree *bind_tree;
85
86     attr_info attrs_info[] = {
87         {"xmlns", hf_xmpp_xmlns, TRUE, TRUE, NULL, NULL},
88         {"resource", hf_xmpp_iq_bind_resource, FALSE, TRUE, NULL, NULL},
89         {"jid", hf_xmpp_iq_bind_jid, FALSE, TRUE, NULL, NULL}
90     };
91
92     col_append_fstr(pinfo->cinfo, COL_INFO, "BIND ");
93
94     bind_item = proto_tree_add_item(tree, hf_xmpp_iq_bind, tvb, element->offset, element->length, ENC_BIG_ENDIAN);
95     bind_tree = proto_item_add_subtree(bind_item, ett_xmpp_iq_bind);
96
97     change_elem_to_attrib("resource", "resource", element, transform_func_cdata);
98     change_elem_to_attrib("jid", "jid", element, transform_func_cdata);
99
100     display_attrs(bind_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info));
101
102     xmpp_unknown(bind_tree, tvb, pinfo, element);
103 }
104
105 void
106 xmpp_session(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element)
107 {
108     proto_item *session_item;
109     proto_tree *session_tree;
110
111     attr_info attrs_info [] = {
112         {"xmlns", hf_xmpp_xmlns, TRUE, TRUE, NULL, NULL}
113     };
114
115     session_item = proto_tree_add_item(tree, hf_xmpp_iq_session, tvb, element->offset, element->length, ENC_BIG_ENDIAN);
116     session_tree = proto_item_add_subtree(session_item, ett_xmpp_iq_session);
117
118     col_append_fstr(pinfo->cinfo, COL_INFO, "SESSION ");
119
120     display_attrs(session_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info));
121     display_elems(session_tree, element, pinfo, tvb, NULL, 0);
122 }
123
124 void
125 xmpp_vcard(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element)
126 {
127     proto_item *vcard_item;
128     proto_tree *vcard_tree;
129
130     attr_info attrs_info[] = {
131         {"xmlns", hf_xmpp_xmlns, TRUE, TRUE, NULL, NULL},
132         {"value", -1, FALSE, FALSE, NULL, NULL}
133     };
134
135     element_t *cdata;
136
137     col_append_fstr(pinfo->cinfo, COL_INFO, "VCARD ");
138
139     vcard_item = proto_tree_add_item(tree, hf_xmpp_vcard, tvb, element->offset, element->length, ENC_BIG_ENDIAN);
140     vcard_tree = proto_item_add_subtree(vcard_item, ett_xmpp_vcard);
141
142     cdata = get_first_element(element);
143
144     if(cdata)
145     {
146         attr_t *fake_cdata;
147         fake_cdata = ep_init_attr_t(element_to_string(tvb, cdata), cdata->offset, cdata->length);
148         g_hash_table_insert(element->attrs,"value", fake_cdata);
149
150     }
151     display_attrs(vcard_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info));
152
153 }
154
155 void
156 xmpp_vcard_x_update(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element)
157 {
158     proto_item *x_item;
159     proto_tree *x_tree;
160
161     attr_info attrs_info[] = {
162         {"xmlns", hf_xmpp_xmlns, TRUE, FALSE, NULL, NULL},
163         {"photo", -1, FALSE, FALSE, NULL, NULL}
164     };
165
166     element_t *photo;
167
168     x_item = proto_tree_add_item(tree, hf_xmpp_vcard_x_update, tvb, element->offset, element->length, ENC_BIG_ENDIAN);
169     x_tree = proto_item_add_subtree(x_item, ett_xmpp_vcard_x_update);
170
171     if((photo = steal_element_by_name(element, "photo"))!=NULL)
172     {
173         attr_t *fake_photo = ep_init_attr_t(photo->data?photo->data->value:"", photo->offset, photo->length);
174         g_hash_table_insert(element->attrs, "photo", fake_photo);
175     }
176
177     display_attrs(x_tree, element,pinfo, tvb, attrs_info, array_length(attrs_info));
178
179     xmpp_unknown(x_tree, tvb, pinfo, element);
180 }
181
182 void
183 xmpp_disco_items_query(proto_tree *tree, tvbuff_t *tvb, packet_info* pinfo, element_t *element)
184 {
185     proto_item *query_item;
186     proto_tree *query_tree;
187
188     attr_info attrs_info[] = {
189         {"xmlns", hf_xmpp_xmlns, TRUE, TRUE, NULL, NULL},
190         {"node", hf_xmpp_query_node, FALSE, TRUE, NULL, NULL}
191     };
192
193     element_t *item;
194
195     col_append_fstr(pinfo->cinfo, COL_INFO, "QUERY(disco#items) ");
196
197     query_item = proto_tree_add_item(tree, hf_xmpp_query, tvb, element->offset, element->length, ENC_BIG_ENDIAN);
198     query_tree = proto_item_add_subtree(query_item, ett_xmpp_query);
199
200     display_attrs(query_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info));
201
202     while((item = steal_element_by_name(element, "item")) != NULL)
203     {
204         xmpp_disco_items_item(query_tree, tvb, pinfo, item);
205     }
206
207     xmpp_unknown(query_tree, tvb, pinfo, element);
208 }
209
210 static void
211 xmpp_disco_items_item(proto_tree *tree, tvbuff_t *tvb, packet_info* pinfo, element_t *element)
212 {
213     proto_item *item_item;
214     proto_tree *item_tree;
215
216     attr_info attrs_info[] = {
217         {"jid", hf_xmpp_query_item_jid, TRUE, TRUE, NULL, NULL},
218         {"name", hf_xmpp_query_item_name, FALSE, TRUE, NULL, NULL},
219         {"node", hf_xmpp_query_item_node, FALSE, TRUE, NULL, NULL}
220     };
221
222     item_item = proto_tree_add_item(tree, hf_xmpp_query_item, tvb, element->offset, element->length, ENC_BIG_ENDIAN);
223     item_tree = proto_item_add_subtree(item_item, ett_xmpp_query_item);
224
225     display_attrs(item_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info));
226
227     xmpp_unknown(item_tree, tvb, pinfo, element);
228 }
229
230 void
231 xmpp_roster_query(proto_tree *tree, tvbuff_t *tvb, packet_info* pinfo, element_t *element)
232 {
233     proto_item *query_item;
234     proto_tree *query_tree;
235
236     attr_info attrs_info[] = {
237         {"xmlns", hf_xmpp_xmlns, TRUE, TRUE, NULL, NULL},
238         {"ver", -1, FALSE, TRUE, NULL, NULL},
239     };
240
241     elem_info elems_info[] = {
242         {NAME, "item", xmpp_roster_item, MANY},
243     };
244
245     col_append_fstr(pinfo->cinfo, COL_INFO, "QUERY(jabber:iq:roster) ");
246
247     query_item = proto_tree_add_item(tree, hf_xmpp_query, tvb, element->offset, element->length, ENC_BIG_ENDIAN);
248     query_tree = proto_item_add_subtree(query_item, ett_xmpp_query);
249
250     display_attrs(query_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info));
251     display_elems(query_tree, element, pinfo, tvb, elems_info, array_length(elems_info));
252 }
253
254 static void
255 xmpp_roster_item(proto_tree *tree, tvbuff_t *tvb, packet_info* pinfo, element_t *element)
256 {
257     proto_item *item_item;
258     proto_tree *item_tree;
259
260     const gchar *ask_enums[] = {"subscribe"};
261     const gchar *subscription_enums[] = {"both","from","none","remove","to"};
262
263     array_t *ask_enums_array = ep_init_array_t(ask_enums,array_length(ask_enums));
264     array_t *subscription_array = ep_init_array_t(subscription_enums,array_length(subscription_enums));
265
266     attr_info attrs_info[] = {
267         {"jid", hf_xmpp_query_item_jid, TRUE, TRUE, NULL, NULL},
268         {"name", hf_xmpp_query_item_name, FALSE, TRUE, NULL, NULL},
269         {"ask", hf_xmpp_query_item_ask, FALSE, TRUE, val_enum_list, ask_enums_array},
270         {"approved", hf_xmpp_query_item_approved, FALSE, TRUE, NULL, NULL},
271         {"subscription", hf_xmpp_query_item_subscription, FALSE, TRUE, val_enum_list, subscription_array},
272     };
273
274     element_t *group;
275
276     item_item = proto_tree_add_item(tree, hf_xmpp_query_item, tvb, element->offset, element->length, ENC_BIG_ENDIAN);
277     item_tree = proto_item_add_subtree(item_item, ett_xmpp_query_item);
278
279     display_attrs(item_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info));
280
281     while((group = steal_element_by_name(element,"group"))!=NULL)
282     {
283         proto_tree_add_string(item_tree, hf_xmpp_query_item_group, tvb, group->offset, group->length, elem_cdata(group));
284     }
285
286     xmpp_unknown(item_tree, tvb, pinfo, element);
287 }
288
289 void
290 xmpp_disco_info_query(proto_tree *tree,  tvbuff_t *tvb, packet_info *pinfo, element_t *element)
291 {
292     proto_item *query_item;
293     proto_tree *query_tree;
294
295     attr_info attrs_info[] = {
296         {"xmlns", hf_xmpp_xmlns, TRUE, TRUE, NULL, NULL},
297         {"node", hf_xmpp_query_node, FALSE, TRUE, NULL, NULL}
298     };
299
300     element_t *identity, *feature, *x_data;
301
302     col_append_fstr(pinfo->cinfo, COL_INFO, "QUERY(disco#info) ");
303
304     query_item = proto_tree_add_item(tree, hf_xmpp_query, tvb, element->offset, element->length, ENC_BIG_ENDIAN);
305     query_tree = proto_item_add_subtree(query_item, ett_xmpp_query);
306
307     display_attrs(query_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info));
308
309
310     while((identity = steal_element_by_name(element, "identity")) != NULL)
311     {
312         xmpp_disco_info_identity(query_tree, tvb, pinfo, identity);
313     }
314
315     while((feature = steal_element_by_name(element, "feature")) != NULL)
316     {
317         xmpp_disco_info_feature(query_tree, tvb, feature);
318     }
319
320     if((x_data = steal_element_by_name_and_attr(element, "x", "xmlns", "jabber:x:data")) != NULL)
321     {
322         xmpp_x_data(query_tree, tvb, pinfo, x_data);
323     }
324
325     xmpp_unknown(query_tree, tvb, pinfo, element);
326 }
327
328 static void
329 xmpp_disco_info_identity(proto_tree *tree, tvbuff_t *tvb, packet_info* pinfo, element_t *element)
330 {
331     proto_item *identity_item;
332     proto_tree *identity_tree;
333
334     attr_info attrs_info[] = {
335         {"category", hf_xmpp_query_identity_category, TRUE, TRUE, NULL, NULL},
336         {"name", hf_xmpp_query_identity_name, FALSE, TRUE, NULL, NULL},
337         {"type", hf_xmpp_query_identity_type, TRUE, TRUE, NULL, NULL}
338     };
339
340     identity_item = proto_tree_add_item(tree, hf_xmpp_query_identity, tvb, element->offset, element->length, ENC_BIG_ENDIAN);
341     identity_tree = proto_item_add_subtree(identity_item, ett_xmpp_query_identity);
342
343     display_attrs(identity_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info));
344
345     xmpp_unknown(identity_tree, tvb, pinfo, element);
346
347 }
348
349 static void
350 xmpp_disco_info_feature(proto_tree *tree, tvbuff_t *tvb, element_t *element)
351 {
352
353     attr_t *var = get_attr(element, "var");
354
355     if(var)
356     {
357         proto_tree_add_string_format(tree, hf_xmpp_query_feature, tvb, var->offset, var->length, var->value, "FEATURE [%s]", var->value);
358     }
359 }
360
361 void
362 xmpp_bytestreams_query(proto_tree *tree,  tvbuff_t *tvb, packet_info *pinfo, element_t *element)
363 {
364     proto_item *query_item;
365     proto_tree *query_tree;
366
367     const gchar *mode_enums[] = {"tcp", "udp"};
368     array_t *mode_array = ep_init_array_t(mode_enums, array_length(mode_enums));
369
370     attr_info attrs_info[] = {
371         {"xmlns", hf_xmpp_xmlns, TRUE, TRUE, NULL, NULL},
372         {"sid", -1, FALSE, TRUE, NULL, NULL},
373         {"mode", -1, FALSE, TRUE, val_enum_list, mode_array},
374         {"dstaddr", -1, FALSE, TRUE, NULL, NULL}
375     };
376
377     element_t *streamhost, *streamhost_used, *activate, *udpsuccess;
378
379     col_append_fstr(pinfo->cinfo, COL_INFO, "QUERY(bytestreams) ");
380
381     query_item = proto_tree_add_item(tree, hf_xmpp_query, tvb, element->offset, element->length, ENC_BIG_ENDIAN);
382     query_tree = proto_item_add_subtree(query_item, ett_xmpp_query);
383
384     display_attrs(query_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info));
385
386
387     while((streamhost = steal_element_by_name(element, "streamhost")) != NULL)
388     {
389         xmpp_bytestreams_streamhost(query_tree, tvb, pinfo, streamhost);
390     }
391
392     if((streamhost_used = steal_element_by_name(element, "streamhost-used")) != NULL)
393     {
394         xmpp_bytestreams_streamhost_used(query_tree, tvb, pinfo, streamhost_used);
395     }
396
397     if((activate = steal_element_by_name(element, "activate")) != NULL)
398     {
399         xmpp_bytestreams_activate(query_tree, tvb, pinfo, activate);
400     }
401
402     if((udpsuccess = steal_element_by_name(element, "udpsuccess")) != NULL)
403     {
404         xmpp_bytestreams_udpsuccess(query_tree, tvb, pinfo, udpsuccess);
405     }
406
407     xmpp_unknown(query_tree, tvb, pinfo, element);
408 }
409
410 static void
411 xmpp_bytestreams_streamhost(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element)
412 {
413     proto_item *sh_item;
414     proto_tree *sh_tree;
415
416     attr_info attrs_info[] = {
417         {"jid", -1, TRUE, TRUE, NULL, NULL},
418         {"host", -1, TRUE, TRUE, NULL, NULL},
419         {"port", -1, FALSE, TRUE, NULL, NULL}
420     };
421
422     sh_item = proto_tree_add_item(tree, hf_xmpp_query_streamhost, tvb, element->offset, element->length, ENC_BIG_ENDIAN);
423     sh_tree = proto_item_add_subtree(sh_item, ett_xmpp_query_streamhost);
424
425     display_attrs(sh_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info));
426
427     xmpp_unknown(sh_tree, tvb, pinfo, element);
428 }
429
430 static void
431 xmpp_bytestreams_streamhost_used(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element)
432 {
433     proto_item *shu_item;
434     proto_tree *shu_tree;
435
436     attr_info attrs_info[] = {
437         {"jid", -1, TRUE, TRUE, NULL, NULL}
438     };
439
440     shu_item = proto_tree_add_item(tree, hf_xmpp_query_streamhost_used, tvb, element->offset, element->length, ENC_BIG_ENDIAN);
441     shu_tree = proto_item_add_subtree(shu_item, ett_xmpp_query_streamhost_used);
442
443     display_attrs(shu_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info));
444
445     xmpp_unknown(shu_tree, tvb, pinfo, element);
446 }
447
448 static void
449 xmpp_bytestreams_activate(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element)
450 {
451     proto_tree_add_string(tree, hf_xmpp_query_activate, tvb, element->offset, element->length, elem_cdata(element));
452     xmpp_unknown(tree, tvb, pinfo, element);
453 }
454
455 static void
456 xmpp_bytestreams_udpsuccess(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element)
457 {
458     proto_item *udps_item;
459     proto_tree *udps_tree;
460
461     attr_info attrs_info[] = {
462         {"dstaddr", -1, TRUE, TRUE, NULL, NULL}
463     };
464
465     udps_item = proto_tree_add_item(tree, hf_xmpp_query_udpsuccess, tvb, element->offset, element->length, ENC_BIG_ENDIAN);
466     udps_tree =proto_item_add_subtree(udps_item, ett_xmpp_query_udpsuccess);
467
468     display_attrs(udps_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info));
469
470     xmpp_unknown(udps_tree, tvb, pinfo, element);
471 }
472
473
474
475 /*SI File Transfer*/
476 void
477 xmpp_si(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element)
478 {
479     proto_item *si_item;
480     proto_tree *si_tree;
481
482     attr_info attrs_info[] = {
483         {"xmlns", hf_xmpp_xmlns, TRUE, TRUE, NULL, NULL},
484         {"id", -1, FALSE, FALSE, NULL, NULL},
485         {"mime-type", -1, FALSE, TRUE, NULL, NULL},
486         {"profile", -1, FALSE, TRUE, NULL, NULL}
487     };
488
489     element_t *file, *feature_neg;
490
491     col_append_fstr(pinfo->cinfo, COL_INFO, "SI ");
492
493     si_item = proto_tree_add_item(tree, hf_xmpp_si, tvb, element->offset, element->length, ENC_BIG_ENDIAN);
494     si_tree = proto_item_add_subtree(si_item, ett_xmpp_si);
495
496     display_attrs(si_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info));
497
498     while((file = steal_element_by_name(element, "file"))!=NULL)
499     {
500         xmpp_si_file(si_tree, tvb, pinfo, file);
501     }
502
503     while((feature_neg = steal_element_by_name(element, "feature"))!=NULL)
504     {
505         xmpp_feature_neg(si_tree, tvb, pinfo, feature_neg);
506     }
507
508
509
510     xmpp_unknown(si_tree, tvb, pinfo, element);
511 }
512
513 static void
514 xmpp_si_file(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element)
515 {
516     proto_item *file_item;
517     proto_tree *file_tree;
518
519     attr_info attrs_info[]  ={
520         {"xmlns", hf_xmpp_xmlns, TRUE, FALSE, NULL, NULL},
521         {"name", -1, TRUE, TRUE, NULL, NULL},
522         {"size", -1, TRUE, TRUE, NULL, NULL},
523         {"date", -1, FALSE, FALSE, NULL, NULL},
524         {"hash", -1, FALSE, FALSE, NULL, NULL},
525         {"desc", -1, FALSE, FALSE, NULL, NULL}
526     };
527
528     element_t *desc, *range;
529
530     file_item = proto_tree_add_item(tree, hf_xmpp_si_file, tvb, element->offset, element->length, ENC_BIG_ENDIAN);
531     file_tree = proto_item_add_subtree(file_item, ett_xmpp_si_file);
532
533     if((desc = steal_element_by_name(element, "desc"))!=NULL)
534     {
535          attr_t *fake_desc = ep_init_attr_t(desc->data?desc->data->value:"", desc->offset, desc->length);
536          g_hash_table_insert(element->attrs, "desc", fake_desc);
537     }
538
539     if((range = steal_element_by_name(element, "range"))!=NULL)
540     {
541         xmpp_si_file_range(file_tree, tvb, pinfo, range);
542     }
543
544     display_attrs(file_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info));
545
546     xmpp_unknown(file_tree, tvb, pinfo, element);
547 }
548
549 static void
550 xmpp_si_file_range(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element)
551 {
552     proto_item *range_item;
553     proto_tree *range_tree;
554
555     attr_info attrs_info[] = {
556         {"offset", -1, FALSE, TRUE, NULL, NULL},
557         {"length", -1, FALSE, TRUE, NULL, NULL}
558     };
559
560     range_item = proto_tree_add_text(tree, tvb, element->offset, element->length, "RANGE: ");
561     range_tree = proto_item_add_subtree(range_item, ett_xmpp_si_file_range);
562
563     display_attrs(range_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info));
564
565     xmpp_unknown(range_tree, tvb, pinfo, element);
566
567 }
568
569 /*Feature Negotiation*/
570 void
571 xmpp_feature_neg(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element)
572 {
573     proto_item *feature_item;
574     proto_tree *feature_tree;
575
576     attr_info attrs_info[] = {
577         {"xmlns", hf_xmpp_xmlns, TRUE, TRUE, NULL, NULL}
578     };
579
580     element_t *x_data;
581
582     feature_item = proto_tree_add_item(tree, hf_xmpp_iq_feature_neg, tvb, element->offset, element->length, ENC_BIG_ENDIAN);
583     feature_tree = proto_item_add_subtree(feature_item, ett_xmpp_iq_feature_neg);
584
585     display_attrs(feature_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info));
586
587     while((x_data = steal_element_by_name_and_attr(element, "x", "xmlns", "jabber:x:data"))!=NULL)
588     {
589         xmpp_x_data(feature_tree, tvb, pinfo, x_data);
590     }
591
592     xmpp_unknown(feature_tree, tvb, pinfo, element);
593 }
594
595
596 /*jabber:x:data*/
597 void
598 xmpp_x_data(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element)
599 {
600     proto_item *x_item;
601     proto_tree *x_tree;
602
603     const gchar *type_enums[] = {"cancel", "form", "result", "submit"};
604     array_t *type_array = ep_init_array_t(type_enums, array_length(type_enums));
605
606     attr_info attrs_info[] = {
607         {"xmlns", hf_xmpp_xmlns, TRUE, FALSE, NULL, NULL},
608         {"type", -1, TRUE, TRUE, val_enum_list, type_array},
609         {"TITLE", -1, FALSE, TRUE, NULL, NULL}
610     };
611
612     elem_info elems_info[] = {
613         {NAME, "instructions", xmpp_x_data_instr, MANY},
614         {NAME, "field", xmpp_x_data_field, MANY},
615     };
616     /*TODO reported, item*/
617
618     x_item = proto_tree_add_item(tree, hf_xmpp_x_data, tvb, element->offset, element->length, ENC_BIG_ENDIAN);
619     x_tree = proto_item_add_subtree(x_item, ett_xmpp_x_data);
620
621     change_elem_to_attrib("title", "TITLE", element, transform_func_cdata);
622
623     display_attrs(x_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info));
624     display_elems(x_tree, element, pinfo, tvb, elems_info, array_length(elems_info));
625 }
626
627 static void
628 xmpp_x_data_field(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element)
629 {
630     proto_item *field_item;
631     proto_tree *field_tree;
632
633     const gchar *type_enums[] = {"boolean", "fixed", "hidden", "jid-multi",
634         "jid-single", "list-multi", "list-single", "text-multi", "text-single",
635         "text-private"
636     };
637     array_t *type_array = ep_init_array_t(type_enums, array_length(type_enums));
638
639     attr_info attrs_info[] =
640     {
641         {"label", -1, FALSE, TRUE, NULL, NULL},
642         {"type", -1, FALSE, TRUE, val_enum_list, type_array},
643         {"var", -1, FALSE, TRUE, NULL, NULL}
644     };
645
646     element_t /**desc, *required,*/ *value, *option;
647
648     field_item = proto_tree_add_item(tree, hf_xmpp_x_data_field, tvb, element->offset, element->length, ENC_BIG_ENDIAN);
649     field_tree = proto_item_add_subtree(field_item, ett_xmpp_x_data_field);
650
651     display_attrs(field_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info));
652
653     while((option = steal_element_by_name(element, "option"))!=NULL)
654     {
655         xmpp_x_data_field_option(field_tree, tvb, pinfo, option);
656     }
657
658     while((value = steal_element_by_name(element, "value"))!=NULL)
659     {
660         xmpp_x_data_field_value(field_tree, tvb, pinfo, value);
661     }
662
663     xmpp_unknown(field_item, tvb, pinfo, element);
664
665 }
666
667 static void
668 xmpp_x_data_field_option(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element)
669 {
670     proto_item *option_item;
671     proto_tree *option_tree;
672
673     attr_info attrs_info[] = {
674         {"label", -1, FALSE, TRUE, NULL, NULL},
675         {"value", -1, FALSE, TRUE, NULL, NULL}
676     };
677
678     element_t *value;
679
680     option_item = proto_tree_add_item(tree, hf_xmpp_x_data_field_value, tvb, element->offset, element->length, ENC_BIG_ENDIAN);
681     option_tree = proto_item_add_subtree(option_item, ett_xmpp_x_data_field_value);
682
683     if((value = steal_element_by_name(element, "value"))!=NULL)
684     {
685         attr_t *fake_value = ep_init_attr_t(value->data?value->data->value:"",value->offset, value->length);
686         g_hash_table_insert(element->attrs, "value", fake_value);
687     }
688
689     display_attrs(option_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info));
690
691     xmpp_unknown(option_tree, tvb, pinfo, element);
692 }
693
694 static void
695 xmpp_x_data_field_value(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element)
696 {
697     proto_item *value_item;
698     proto_tree *value_tree;
699
700     attr_info attrs_info[] = {
701         {"label", -1, FALSE, TRUE, NULL, NULL},
702         {"value", -1, TRUE, TRUE, NULL, NULL}
703     };
704     attr_t *fake_value;
705
706     value_item = proto_tree_add_item(tree, hf_xmpp_x_data_field_value, tvb, element->offset, element->length, ENC_BIG_ENDIAN);
707     value_tree = proto_item_add_subtree(value_item, ett_xmpp_x_data_field_value);
708
709
710
711    fake_value = ep_init_attr_t(element->data?element->data->value:"",element->offset, element->length);
712    g_hash_table_insert(element->attrs, "value", fake_value);
713
714
715     display_attrs(value_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info));
716
717     xmpp_unknown(value_tree, tvb, pinfo, element);
718 }
719
720 static void
721 xmpp_x_data_instr(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo _U_, element_t* element)
722 {
723     proto_tree_add_text(tree, tvb, element->offset, element->length, "INSTRUCTIONS: %s",elem_cdata(element));
724 }
725
726 /*In-Band Bytestreams*/
727 void
728 xmpp_ibb_open(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element)
729 {
730     proto_item *open_item;
731     proto_tree *open_tree;
732
733     const gchar *stanza_enums[] = {"iq","message"};
734     array_t *stanza_array = ep_init_array_t(stanza_enums, array_length(stanza_enums));
735
736     attr_info attrs_info[] = {
737         {"xmlns", hf_xmpp_xmlns, TRUE, FALSE, NULL, NULL},
738         {"sid", -1, TRUE, TRUE, NULL, NULL},
739         {"block-size", -1, TRUE, TRUE, NULL, NULL},
740         {"stanza", -1, FALSE, TRUE, val_enum_list, stanza_array}
741     };
742
743     col_append_fstr(pinfo->cinfo, COL_INFO, "IBB-OPEN ");
744
745     open_item = proto_tree_add_item(tree, hf_xmpp_ibb_open, tvb, element->offset, element->length, ENC_BIG_ENDIAN);
746     open_tree = proto_item_add_subtree(open_item, ett_xmpp_ibb_open);
747
748     display_attrs(open_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info));
749     xmpp_unknown(open_tree, tvb, pinfo, element);
750 }
751
752 void
753 xmpp_ibb_close(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element)
754 {
755     proto_item *close_item;
756     proto_tree *close_tree;
757
758     attr_info attrs_info[] = {
759         {"xmlns", hf_xmpp_xmlns, TRUE, FALSE, NULL, NULL},
760         {"sid", -1, TRUE, TRUE, NULL, NULL}
761     };
762
763     col_append_fstr(pinfo->cinfo, COL_INFO, "IBB-CLOSE ");
764
765     close_item = proto_tree_add_item(tree, hf_xmpp_ibb_close, tvb, element->offset, element->length, ENC_BIG_ENDIAN);
766     close_tree = proto_item_add_subtree(close_item, ett_xmpp_ibb_close);
767
768     display_attrs(close_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info));
769     xmpp_unknown(close_tree, tvb, pinfo, element);
770 }
771
772 void
773 xmpp_ibb_data(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element)
774 {
775     proto_item *data_item;
776     proto_tree *data_tree;
777
778     attr_info attrs_info[] = {
779         {"xmlns", hf_xmpp_xmlns, TRUE, FALSE, NULL, NULL},
780         {"sid", -1, TRUE, TRUE, NULL, NULL},
781         {"seq", -1, TRUE, TRUE, NULL, NULL},
782         {"value", -1, FALSE, FALSE, NULL, NULL}
783     };
784
785     col_append_fstr(pinfo->cinfo, COL_INFO, "IBB-DATA ");
786
787     data_item = proto_tree_add_item(tree, hf_xmpp_ibb_data, tvb, element->offset, element->length, ENC_BIG_ENDIAN);
788     data_tree = proto_item_add_subtree(data_item, ett_xmpp_ibb_data);
789
790     if(element->data)
791     {
792         attr_t *fake_data = ep_init_attr_t(element->data->value, element->offset, element->length);
793         g_hash_table_insert(element->attrs, "value", fake_data);
794     }
795
796     display_attrs(data_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info));
797     xmpp_unknown(data_tree, tvb, pinfo, element);
798 }
799
800
801 /*Delayed Delivery urn:xmpp:delay and jabber:x:delay*/
802 void
803 xmpp_delay(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element)
804 {
805     proto_item *delay_item;
806     proto_tree *delay_tree;
807
808     attr_info attrs_info[]={
809         {"xmlns", hf_xmpp_xmlns, TRUE, FALSE, NULL, NULL},
810         {"from", -1, FALSE, TRUE, NULL, NULL},
811         {"stamp", -1, TRUE, TRUE, NULL, NULL},
812         {"value", -1, FALSE, TRUE, NULL, NULL}
813     };
814
815     delay_item = proto_tree_add_item(tree, hf_xmpp_delay, tvb, element->offset, element->length, ENC_BIG_ENDIAN);
816     delay_tree = proto_item_add_subtree(delay_item, ett_xmpp_delay);
817
818     if(element->data)
819     {
820         attr_t *fake_value = ep_init_attr_t(element->data->value, element->offset, element->length);
821         g_hash_table_insert(element->attrs, "value", fake_value);
822     }
823
824     display_attrs(delay_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info));
825
826     xmpp_unknown(delay_tree, tvb, pinfo, element);
827 }
828
829 /*Entity Capabilities http://jabber.org/protocol/caps*/
830 void
831 xmpp_presence_caps(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element)
832 {
833     proto_item *caps_item;
834     proto_tree *caps_tree;
835
836     attr_info attrs_info[] = {
837         {"xmlns", hf_xmpp_xmlns, TRUE, FALSE, NULL, NULL},
838         {"ext", -1, FALSE, FALSE, NULL, NULL},
839         {"hash", -1, TRUE, TRUE, NULL, NULL},
840         {"node", -1, TRUE, TRUE, NULL, NULL},
841         {"ver", -1, TRUE, FALSE, NULL, NULL}
842     };
843
844     caps_item = proto_tree_add_item(tree, hf_xmpp_presence_caps, tvb, element->offset, element->length, ENC_BIG_ENDIAN);
845     caps_tree = proto_item_add_subtree(caps_item, ett_xmpp_presence_caps);
846
847     display_attrs(caps_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info));
848
849     xmpp_unknown(caps_tree, tvb, pinfo, element);
850 }
851
852 /*Message Events jabber:x:event*/
853 void
854 xmpp_x_event(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element)
855 {
856     proto_item *x_item;
857     proto_tree *x_tree;
858
859     attr_info attrs_info[] = {
860         {"xmlns", hf_xmpp_xmlns, TRUE, FALSE, NULL, NULL},
861         {"condition", hf_xmpp_x_event_condition, TRUE, TRUE, NULL, NULL},
862         {"id", -1, FALSE, TRUE, NULL, NULL}
863     };
864
865     const gchar *cond_names[] = {"offline", "delivered", "displayed", "composing"};
866
867     attr_t *fake_cond;
868
869     element_t *cond, *id;
870
871     gchar *cond_value = ep_strdup("");
872
873     x_item =  proto_tree_add_item(tree, hf_xmpp_x_event, tvb, element->offset, element->length, ENC_BIG_ENDIAN);
874     x_tree = proto_item_add_subtree(x_item, ett_xmpp_x_event);
875
876     if((id = steal_element_by_name(element, "id"))!=NULL)
877     {
878         attr_t *fake_id = ep_init_attr_t(id->data?id->data->value:"", id->offset, id->length);
879         g_hash_table_insert(element->attrs, "id", fake_id);
880     }
881
882     while((cond = steal_element_by_names(element, cond_names, array_length(cond_names))) != NULL)
883     {
884         if(strcmp(cond_value,"") != 0)
885             cond_value = ep_strdup_printf("%s/%s",cond_value, cond->name);
886         else
887             cond_value = ep_strdup(cond->name);
888     }
889
890     fake_cond = ep_init_attr_t(cond_value, element->offset, element->length);
891     g_hash_table_insert(element->attrs, "condition", fake_cond);
892
893
894     display_attrs(x_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info));
895
896     xmpp_unknown(x_tree, tvb, pinfo, element);
897 }
898
899 /*Multi-User Chat http://jabber.org/protocol/muc*/
900 void
901 xmpp_muc_x(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element)
902 {
903     proto_item *x_item;
904     proto_tree *x_tree;
905
906     attr_info attrs_info [] ={
907         {"xmlns", hf_xmpp_xmlns, TRUE, FALSE, NULL, NULL},
908         {"password", -1, FALSE, TRUE, NULL, NULL}
909     };
910
911     element_t *pass, *hist;
912
913     x_item = proto_tree_add_item(tree, hf_xmpp_muc_x, tvb, element->offset, element->length, ENC_BIG_ENDIAN);
914     x_tree = proto_item_add_subtree(x_item, ett_xmpp_muc_x);
915
916     if((pass = steal_element_by_name(element, "password"))!=NULL)
917     {
918         attr_t *fake_pass = ep_init_attr_t(pass->data?pass->data->value:"",pass->offset, pass->length);
919         g_hash_table_insert(element->attrs, "password", fake_pass);
920     }
921
922     display_attrs(x_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info));
923
924     if((hist = steal_element_by_name(element, "history"))!=NULL)
925     {
926         xmpp_muc_history(x_tree, tvb, pinfo, hist);
927     }
928
929     xmpp_unknown(x_tree, tvb, pinfo, element);
930 }
931
932 static void
933 xmpp_muc_history(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element)
934 {
935     proto_item *hist_item;
936     proto_tree *hist_tree;
937
938     attr_info attrs_info[] = {
939         {"maxchars", -1, FALSE, TRUE, NULL, NULL},
940         {"maxstanzas", -1, FALSE, TRUE, NULL, NULL},
941         {"seconds", -1, FALSE, TRUE, NULL, NULL},
942         {"since", -1, FALSE, TRUE, NULL, NULL}
943     };
944
945     hist_item = proto_tree_add_text(tree, tvb, element->offset, element->length, "HISTORY: ");
946     hist_tree = proto_item_add_subtree(hist_item, ett_xmpp_muc_hist);
947
948     display_attrs(hist_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info));
949
950     xmpp_unknown(hist_tree, tvb, pinfo, element);
951 }
952
953 /*Multi-User Chat http://jabber.org/protocol/muc#user*/
954 void
955 xmpp_muc_user_x(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element)
956 {
957     proto_item *x_item;
958     proto_tree *x_tree;
959
960     attr_info attrs_info[] = {
961         {"xmlns", hf_xmpp_xmlns, TRUE, FALSE, NULL, NULL},
962         {"password", -1, FALSE, TRUE, NULL, NULL}
963     };
964
965     element_t *item, *status, *invite, *password;
966     /*TODO decline destroy*/
967
968     x_item = proto_tree_add_item(tree, hf_xmpp_muc_user_x, tvb, element->offset, element->length, ENC_BIG_ENDIAN);
969     x_tree = proto_item_add_subtree(x_item, ett_xmpp_muc_user_x);
970
971     if((password = steal_element_by_name(element, "password"))!=NULL)
972     {
973         attr_t *fake_pass = ep_init_attr_t(password->data?password->data->value:"",password->offset, password->length);
974         g_hash_table_insert(element->attrs, "password", fake_pass);
975     }
976
977     display_attrs(x_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info));
978
979     while((item = steal_element_by_name(element, "item"))!=NULL)
980     {
981         xmpp_muc_user_item(x_tree, tvb, pinfo, item);
982     }
983
984     while((status = steal_element_by_name(element, "status"))!=NULL)
985     {
986         xmpp_muc_user_status(x_tree, tvb, pinfo, status);
987     }
988
989     while((invite = steal_element_by_name(element, "invite"))!=NULL)
990     {
991         xmpp_muc_user_invite(x_tree, tvb, pinfo, invite);
992     }
993
994     xmpp_unknown(x_tree, tvb, pinfo, element);
995 }
996
997 static void
998 xmpp_muc_user_item(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element)
999 {
1000     proto_item *item_item;
1001     proto_tree *item_tree;
1002
1003     const gchar *affiliation_enums[] = {"admin", "member", "none", "outcast", "owner"};
1004     array_t  *affil_array = ep_init_array_t(affiliation_enums, array_length(affiliation_enums));
1005
1006     const gchar *role_enums[] = {"none", "moderator", "participant", "visitor"};
1007     array_t *role_array = ep_init_array_t(role_enums, array_length(role_enums));
1008
1009     attr_info attrs_info [] ={
1010         {"affiliation", -1, FALSE, TRUE, val_enum_list, affil_array},
1011         {"jid", -1, FALSE, TRUE, NULL, NULL},
1012         {"nick", -1, FALSE, TRUE, NULL, NULL},
1013         {"role", -1, FALSE, TRUE, val_enum_list, role_array},
1014         {"reason", -1, FALSE, TRUE, NULL, NULL},
1015         {"actor_jid", -1, FALSE, TRUE, NULL, NULL}
1016     };
1017
1018     element_t *reason, *actor;
1019     /*TODO continue - it's not clear to me, in schema it's marked as empty, but in examples it has CDATA*/
1020
1021     item_item = proto_tree_add_item(tree, hf_xmpp_muc_user_item, tvb, element->offset, element->length, ENC_BIG_ENDIAN);
1022     item_tree = proto_item_add_subtree(item_item, ett_xmpp_muc_user_item);
1023
1024     if((reason = steal_element_by_name(element, "reason"))!=NULL)
1025     {
1026         attr_t *fake_reason = ep_init_attr_t(reason->data?reason->data->value:"",reason->offset, reason->length);
1027         g_hash_table_insert(element->attrs,"reason",fake_reason);
1028     }
1029
1030     if((actor = steal_element_by_name(element, "actor"))!=NULL)
1031     {
1032         attr_t *jid = get_attr(actor, "jid");
1033         attr_t *fake_actor_jid = ep_init_attr_t(jid?jid->value:"",actor->offset, actor->length);
1034         g_hash_table_insert(element->attrs, "actor_jid", fake_actor_jid);
1035     }
1036
1037     display_attrs(item_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info));
1038
1039     xmpp_unknown(item_tree, tvb, pinfo, element);
1040 }
1041
1042 static void
1043 xmpp_muc_user_status(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element)
1044 {
1045     attr_t *code = get_attr(element, "code");
1046     proto_tree_add_text(tree, tvb, element->offset, element->length, "STATUS [code=\"%s\"]",code?code->value:"");
1047
1048     xmpp_unknown(tree, tvb, pinfo, element);
1049 }
1050
1051 static void
1052 xmpp_muc_user_invite(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element)
1053 {
1054     proto_item *invite_item;
1055     proto_tree *invite_tree;
1056
1057     attr_info attrs_info[] = {
1058         {"from", -1, FALSE, TRUE, NULL, NULL},
1059         {"to", -1, FALSE, TRUE, NULL, NULL},
1060         {"reason", -1, FALSE, TRUE, NULL, NULL}
1061     };
1062
1063     element_t *reason;
1064
1065     invite_item = proto_tree_add_item(tree, hf_xmpp_muc_user_invite, tvb, element->offset, element->length, ENC_BIG_ENDIAN);
1066     invite_tree = proto_item_add_subtree(invite_item, ett_xmpp_muc_user_invite);
1067
1068     if((reason = steal_element_by_name(element, "reason"))!=NULL)
1069     {
1070         attr_t *fake_reason = ep_init_attr_t(reason->data?reason->data->value:"",reason->offset, reason->length);
1071         g_hash_table_insert(element->attrs, "reason", fake_reason);
1072     }
1073
1074     display_attrs(invite_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info));
1075
1076     xmpp_unknown(invite_tree, tvb, pinfo, element);
1077 }
1078
1079 /*Multi-User Chat http://jabber.org/protocol/muc#owner*/
1080 void
1081 xmpp_muc_owner_query(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element)
1082 {
1083     proto_item *query_item;
1084     proto_tree *query_tree;
1085
1086     attr_info attrs_info[] = {
1087         {"xmlns", hf_xmpp_xmlns, TRUE, TRUE, NULL, NULL}
1088     };
1089
1090     element_t *x_data;
1091     /*TODO destroy*/
1092
1093     col_append_fstr(pinfo->cinfo, COL_INFO, "QUERY(muc#owner) ");
1094
1095     query_item = proto_tree_add_item(tree, hf_xmpp_query, tvb, element->offset, element->length, ENC_BIG_ENDIAN);
1096     query_tree = proto_item_add_subtree(query_item, ett_xmpp_query);
1097
1098     display_attrs(query_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info));
1099
1100     if((x_data = steal_element_by_name_and_attr(element, "x", "xmlns", "jabber:x:data"))!=NULL)
1101     {
1102         xmpp_x_data(query_tree, tvb, pinfo, x_data);
1103     }
1104
1105     xmpp_unknown(query_tree, tvb, pinfo, element);
1106
1107 }
1108
1109 /*Multi-User Chat http://jabber.org/protocol/muc#admin*/
1110 void
1111 xmpp_muc_admin_query(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element)
1112 {
1113     proto_item *query_item;
1114     proto_tree *query_tree;
1115
1116     attr_info attrs_info[] = {
1117         {"xmlns", hf_xmpp_xmlns, TRUE, TRUE, NULL, NULL}
1118     };
1119
1120     element_t *item;
1121
1122     col_append_fstr(pinfo->cinfo, COL_INFO, "QUERY(muc#admin) ");
1123
1124     query_item = proto_tree_add_item(tree, hf_xmpp_query, tvb, element->offset, element->length, ENC_BIG_ENDIAN);
1125     query_tree = proto_item_add_subtree(query_item, ett_xmpp_query);
1126
1127     display_attrs(query_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info));
1128
1129     while((item = steal_element_by_name(element, "item"))!=NULL)
1130     {
1131         /*from muc#user, because it is the same except continue element*/
1132         xmpp_muc_user_item(query_tree, tvb, pinfo, item);
1133     }
1134
1135     xmpp_unknown(query_tree, tvb, pinfo, element);
1136 }
1137
1138 /*Last Activity jabber:iq:last*/
1139 void
1140 xmpp_last_query(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element)
1141 {
1142     proto_item *query_item;
1143     proto_tree *query_tree;
1144
1145     attr_info attrs_info[] = {
1146         {"xmlns", hf_xmpp_xmlns, TRUE, TRUE, NULL, NULL},
1147         {"seconds", -1, FALSE, TRUE, NULL, NULL},
1148         {"value", -1, FALSE, TRUE, NULL, NULL}
1149     };
1150
1151     col_append_fstr(pinfo->cinfo, COL_INFO, "QUERY(jabber:iq:last) ");
1152
1153     query_item = proto_tree_add_item(tree, hf_xmpp_query, tvb, element->offset, element->length, ENC_BIG_ENDIAN);
1154     query_tree = proto_item_add_subtree(query_item, ett_xmpp_query);
1155
1156     if(element->data)
1157     {
1158         attr_t *fake_data = ep_init_attr_t(element->data->value, element->data->offset, element->data->length);
1159         g_hash_table_insert(element->attrs, "value", fake_data);
1160     }
1161
1162     display_attrs(query_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info));
1163     display_elems(query_tree, element, pinfo, tvb, NULL, 0);
1164 }
1165
1166 /*XEP-0092: Software Version jabber:iq:version*/
1167 void
1168 xmpp_version_query(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element)
1169 {
1170       proto_item *query_item;
1171     proto_tree *query_tree;
1172
1173     attr_info attrs_info[] = {
1174         {"xmlns", hf_xmpp_xmlns, TRUE, TRUE, NULL, NULL},
1175         {"name", -1, FALSE, TRUE, NULL, NULL},
1176         {"version", -1, FALSE, TRUE, NULL, NULL},
1177         {"os", -1, FALSE, TRUE, NULL, NULL}
1178     };
1179
1180     element_t *name, *version, *os;
1181
1182     col_append_fstr(pinfo->cinfo, COL_INFO, "QUERY(jabber:iq:version) ");
1183
1184     query_item = proto_tree_add_item(tree, hf_xmpp_query, tvb, element->offset, element->length, ENC_BIG_ENDIAN);
1185     query_tree = proto_item_add_subtree(query_item, ett_xmpp_query);
1186
1187     if((name = steal_element_by_name(element,"name"))!=NULL)
1188     {
1189         attr_t *fake_name = ep_init_attr_t(name->data?name->data->value:"", name->offset, name->length);
1190         g_hash_table_insert(element->attrs, "name", fake_name);
1191     }
1192
1193     if((version = steal_element_by_name(element,"version"))!=NULL)
1194     {
1195         attr_t *fake_version = ep_init_attr_t(version->data?version->data->value:"", version->offset, version->length);
1196         g_hash_table_insert(element->attrs, "version", fake_version);
1197     }
1198
1199     if((os = steal_element_by_name(element,"os"))!=NULL)
1200     {
1201         attr_t *fake_os = ep_init_attr_t(os->data?os->data->value:"", os->offset, os->length);
1202         g_hash_table_insert(element->attrs, "os", fake_os);
1203     }
1204
1205     display_attrs(query_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info));
1206     display_elems(query_tree, element, pinfo, tvb, NULL, 0);
1207 }
1208 /*XEP-0199: XMPP Ping*/
1209 void
1210 xmpp_ping(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element)
1211 {
1212     proto_item *ping_item;
1213     proto_tree *ping_tree;
1214
1215     attr_info attrs_info[] = {
1216         {"xmlns", hf_xmpp_xmlns, TRUE, TRUE, NULL, NULL},
1217     };
1218
1219     col_append_fstr(pinfo->cinfo, COL_INFO, "PING ");
1220
1221     ping_item = proto_tree_add_item(tree, hf_xmpp_ping, tvb, element->offset, element->length, ENC_BIG_ENDIAN);
1222     ping_tree = proto_item_add_subtree(ping_item, ett_xmpp_ping);
1223
1224     display_attrs(ping_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info));
1225     display_elems(ping_tree, element, pinfo, tvb, NULL, 0);
1226 }
1227
1228 /*XEP-0300: Use of Cryptographic Hash Functions in XMPP urn:xmpp:hashes:0*/
1229 void
1230 xmpp_hashes(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element) {
1231     proto_item *hashes_item;
1232     proto_tree *hashes_tree;
1233
1234     attr_info attrs_info[] = {
1235         {"xmlns", hf_xmpp_xmlns, TRUE, TRUE, NULL, NULL},
1236     };
1237     elem_info elems_info[] = {
1238         {NAME, "hash", xmpp_hashes_hash, MANY}
1239     };
1240
1241     hashes_item = proto_tree_add_item(tree, hf_xmpp_hashes, tvb, element->offset, element->length, ENC_BIG_ENDIAN);
1242     hashes_tree = proto_item_add_subtree(hashes_item, ett_xmpp_hashes);
1243
1244     display_attrs(hashes_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info));
1245     display_elems(hashes_tree, element, pinfo, tvb, elems_info, array_length(elems_info));
1246 }
1247
1248 static void
1249 xmpp_hashes_hash(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element)
1250 {
1251     proto_item *hash_item;
1252     proto_tree *hash_tree;
1253
1254     attr_info attrs_info[] = {
1255         {"algo", -1, TRUE, TRUE, NULL, NULL},
1256         {"value", -1, TRUE, TRUE, NULL, NULL}
1257     };
1258
1259     attr_t *fake_cdata = ep_init_attr_t(elem_cdata(element), element->offset, element->length);
1260     g_hash_table_insert(element->attrs, "value", fake_cdata);
1261
1262     hash_item = proto_tree_add_text(tree, tvb, element->offset, element->length, "HASH");
1263     hash_tree = proto_item_add_subtree(hash_item, ett_xmpp_hashes_hash);
1264
1265     display_attrs(hash_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info));
1266     display_elems(hash_tree, element, pinfo, tvb, NULL, 0);
1267 }
1268
1269 /*http://jitsi.org/protocol/inputevt*/
1270 void
1271 xmpp_jitsi_inputevt(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element)
1272 {
1273     proto_item *inputevt_item;
1274     proto_tree *inputevt_tree;
1275
1276     attr_info attrs_info[] = {
1277         {"xmlns", hf_xmpp_xmlns, TRUE, TRUE, NULL, NULL},
1278         {"action", -1, FALSE, TRUE, NULL, NULL}
1279     };
1280
1281     elem_info elems_info[] = {
1282         {NAME, "remote-control", xmpp_jitsi_inputevt_rmt_ctrl, MANY}
1283     };
1284
1285     inputevt_item = proto_tree_add_item(tree, hf_xmpp_jitsi_inputevt, tvb, element->offset, element->length, ENC_BIG_ENDIAN);
1286     inputevt_tree = proto_item_add_subtree(inputevt_item, ett_xmpp_jitsi_inputevt);
1287
1288     display_attrs(inputevt_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info));
1289     display_elems(inputevt_tree, element, pinfo, tvb, elems_info, array_length(elems_info));
1290 }
1291
1292 static void
1293 xmpp_jitsi_inputevt_rmt_ctrl(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element)
1294 {
1295     proto_item *rmt_ctrl_item;
1296     proto_tree *rmt_ctrl_tree;
1297
1298     attr_info attrs_info[] = {
1299         {"xmlns", hf_xmpp_xmlns, FALSE, FALSE, NULL, NULL},
1300         {"action", -1, TRUE, TRUE, NULL, NULL},
1301         {"x", -1, FALSE, TRUE, NULL, NULL},
1302         {"y", -1, FALSE, TRUE, NULL, NULL},
1303         {"btns", -1, FALSE, TRUE, NULL, NULL},
1304         {"keycode", -1, FALSE, TRUE, NULL, NULL},
1305     };
1306
1307     element_t *action;
1308     const gchar *action_names[] = {"mouse-move","mouse-press", "mouse-release", "key-press", "key-release"};
1309
1310     if((action = steal_element_by_names(element, action_names, array_length(action_names)))!=NULL)
1311     {
1312         attr_t *fake_action = ep_init_attr_t(action->name, action->offset, action->length);
1313         g_hash_table_insert(element->attrs,"action", fake_action);
1314
1315         if(strcmp(action->name,"mouse-move") == 0)
1316         {
1317             attr_t *x = get_attr(action,"x");
1318             attr_t *y = get_attr(action,"y");
1319
1320             if(x)
1321                 g_hash_table_insert(element->attrs,"x",x);
1322             if(y)
1323                 g_hash_table_insert(element->attrs,"y",y);
1324         } else if(strcmp(action->name,"mouse-press") == 0 || strcmp(action->name,"mouse-release") == 0)
1325         {
1326             attr_t *btns = get_attr(action,"btns");
1327
1328             if(btns)
1329                 g_hash_table_insert(element->attrs,"btns",btns);
1330         } else if(strcmp(action->name,"key-press") == 0 || strcmp(action->name,"key-release") == 0)
1331         {
1332             attr_t *keycode = get_attr(action,"keycode");
1333
1334             if(keycode)
1335                 g_hash_table_insert(element->attrs,"keycode",keycode);
1336         }
1337
1338     }
1339
1340     rmt_ctrl_item = proto_tree_add_item(tree, hf_xmpp_jitsi_inputevt_rmt_ctrl, tvb, element->offset, element->length, ENC_BIG_ENDIAN);
1341     rmt_ctrl_tree = proto_item_add_subtree(rmt_ctrl_item, ett_xmpp_jitsi_inputevt_rmt_ctrl);
1342
1343     display_attrs(rmt_ctrl_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info));
1344     display_elems(rmt_ctrl_tree, element, pinfo, tvb, NULL, 0);
1345 }
1346 /*
1347 * Editor modelines - http://www.wireshark.org/tools/modelines.html
1348 *
1349 * Local variables:
1350 * c-basic-offset: 4
1351 * tab-width: 8
1352 * indent-tabs-mode: nil
1353 * End:
1354 *
1355 * ex: set shiftwidth=4 tabstop=8 expandtab:
1356 * :indentSize=4:tabSize=8:noTabs=true:
1357 */