2 * Wireshark's XMPP dissector.
4 * Copyright 2011, Mariusz Okroj <okrojmariusz[]gmail.com>
8 * Wireshark - Network traffic analyzer
9 * By Gerald Combs <gerald@wireshark.org>
10 * Copyright 1998 Gerald Combs
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.
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.
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
31 #include <epan/packet.h>
32 #include <epan/expert.h>
33 #include <epan/tvbparse.h>
34 #include <epan/strutil.h>
36 #include <epan/dissectors/packet-xml.h>
38 #include <packet-xmpp.h>
39 #include <packet-xmpp-core.h>
40 #include <packet-xmpp-utils.h>
44 xmpp_iq_reqresp_track(packet_info
*pinfo
, xmpp_element_t
*packet
, xmpp_conv_info_t
*xmpp_info
)
46 xmpp_transaction_t
*xmpp_trans
= NULL
;
51 attr_id
= xmpp_get_attr(packet
, "id");
57 id
= wmem_strdup(wmem_packet_scope(), attr_id
->value
);
59 if (!pinfo
->fd
->flags
.visited
) {
60 xmpp_trans
= (xmpp_transaction_t
*)wmem_tree_lookup_string(xmpp_info
->req_resp
, id
, EMEM_TREE_STRING_NOCASE
);
62 xmpp_trans
->resp_frame
= pinfo
->fd
->num
;
65 char *se_id
= wmem_strdup(wmem_file_scope(), id
);
67 xmpp_trans
= wmem_new(wmem_file_scope(), xmpp_transaction_t
);
68 xmpp_trans
->req_frame
= pinfo
->fd
->num
;
69 xmpp_trans
->resp_frame
= 0;
71 wmem_tree_insert_string(xmpp_info
->req_resp
, se_id
, (void *) xmpp_trans
, EMEM_TREE_STRING_NOCASE
);
76 wmem_tree_lookup_string(xmpp_info
->req_resp
, id
, EMEM_TREE_STRING_NOCASE
);
81 xmpp_jingle_session_track(packet_info
*pinfo
, xmpp_element_t
*packet
, xmpp_conv_info_t
*xmpp_info
)
83 xmpp_element_t
*jingle_packet
;
84 GList
*jingle_packet_l
;
86 jingle_packet_l
= xmpp_find_element_by_name(packet
,"jingle");
87 jingle_packet
= (xmpp_element_t
*)(jingle_packet_l
?jingle_packet_l
->data
:NULL
);
89 if (jingle_packet
&& !pinfo
->fd
->flags
.visited
) {
91 xmpp_attr_t
*attr_sid
;
97 attr_id
= xmpp_get_attr(packet
, "id");
102 attr_sid
= xmpp_get_attr(jingle_packet
, "sid");
107 se_id
= wmem_strdup(wmem_file_scope(), attr_id
->value
);
108 se_sid
= wmem_strdup(wmem_file_scope(), attr_sid
->value
);
110 wmem_tree_insert_string(xmpp_info
->jingle_sessions
, se_id
, (void*) se_sid
, EMEM_TREE_STRING_NOCASE
);
115 xmpp_gtalk_session_track(packet_info
*pinfo
, xmpp_element_t
*packet
, xmpp_conv_info_t
*xmpp_info
)
117 xmpp_element_t
*gtalk_packet
;
118 GList
*gtalk_packet_l
;
120 gtalk_packet_l
= xmpp_find_element_by_name(packet
,"session");
121 gtalk_packet
= (xmpp_element_t
*)(gtalk_packet_l
?gtalk_packet_l
->data
:NULL
);
124 if (gtalk_packet
&& !pinfo
->fd
->flags
.visited
) {
125 xmpp_attr_t
*attr_id
;
126 xmpp_attr_t
*attr_sid
;
131 xmpp_attr_t
*xmlns
= xmpp_get_attr(gtalk_packet
, "xmlns");
132 if(xmlns
&& strcmp(xmlns
->value
,"http://www.google.com/session") != 0)
135 attr_id
= xmpp_get_attr(packet
, "id");
140 attr_sid
= xmpp_get_attr(gtalk_packet
, "id");
145 se_id
= wmem_strdup(wmem_file_scope(), attr_id
->value
);
146 se_sid
= wmem_strdup(wmem_file_scope(), attr_sid
->value
);
148 wmem_tree_insert_string(xmpp_info
->gtalk_sessions
, se_id
, (void*) se_sid
, EMEM_TREE_STRING_NOCASE
);
153 xmpp_ibb_session_track(packet_info
*pinfo
, xmpp_element_t
*packet
, xmpp_conv_info_t
*xmpp_info
)
155 xmpp_element_t
*ibb_packet
= NULL
;
158 if(strcmp(packet
->name
, "message") == 0)
160 ibb_packet_l
= xmpp_find_element_by_name(packet
,"data");
161 ibb_packet
= (xmpp_element_t
*)(ibb_packet_l
?ibb_packet_l
->data
:NULL
);
163 } else if(strcmp(packet
->name
, "iq") == 0)
165 ibb_packet_l
= xmpp_find_element_by_name(packet
,"open");
168 ibb_packet_l
= xmpp_find_element_by_name(packet
,"close");
170 ibb_packet_l
= xmpp_find_element_by_name(packet
,"data");
172 ibb_packet
= (xmpp_element_t
*)(ibb_packet_l
?ibb_packet_l
->data
:NULL
);
175 if (ibb_packet
&& !pinfo
->fd
->flags
.visited
) {
176 xmpp_attr_t
*attr_id
;
177 xmpp_attr_t
*attr_sid
;
183 attr_id
= xmpp_get_attr(packet
, "id");
184 attr_sid
= xmpp_get_attr(ibb_packet
, "sid");
185 if(attr_id
&& attr_sid
)
187 se_id
= wmem_strdup(wmem_file_scope(), attr_id
->value
);
188 se_sid
= wmem_strdup(wmem_file_scope(), attr_sid
->value
);
189 wmem_tree_insert_string(xmpp_info
->ibb_sessions
, se_id
, (void*) se_sid
, EMEM_TREE_STRING_NOCASE
);
195 xmpp_unknown_items(proto_tree
*tree
, tvbuff_t
*tvb
, packet_info
*pinfo
, xmpp_element_t
*element
, guint level
)
197 GList
*childs
= element
->elements
;
199 DISSECTOR_ASSERT( level
< ETT_UNKNOWN_LEN
);
201 xmpp_unknown_attrs(tree
, tvb
, pinfo
, element
, TRUE
);
205 proto_tree_add_text(tree
, tvb
, element
->data
->offset
, element
->data
->length
, "CDATA: %s",element
->data
->value
);
210 xmpp_element_t
*child
= (xmpp_element_t
*)childs
->data
;
211 proto_item
*child_item
= proto_tree_add_text(tree
, tvb
, child
->offset
, child
->length
, "%s", xmpp_ep_string_upcase(child
->name
));
212 proto_tree
*child_tree
= proto_item_add_subtree(child_item
, ett_unknown
[level
]);
214 if(child
->default_ns_abbrev
)
215 proto_item_append_text(child_item
, "(%s)", child
->default_ns_abbrev
);
217 xmpp_unknown_items(child_tree
, tvb
, pinfo
, child
, level
+1);
219 childs
= childs
->next
;
224 xmpp_unknown(proto_tree
*tree
, tvbuff_t
*tvb
, packet_info
*pinfo
, xmpp_element_t
*element
)
226 GList
*childs
= element
->elements
;
228 /*element has unrecognized elements*/
231 xmpp_element_t
*child
= (xmpp_element_t
*)childs
->data
;
234 proto_item
*unknown_item
;
235 proto_tree
*unknown_tree
;
237 unknown_item
= proto_tree_add_string_format(tree
,
238 hf_xmpp_unknown
, tvb
, child
->offset
, child
->length
, child
->name
,
239 "%s", xmpp_ep_string_upcase(child
->name
));
241 unknown_tree
= proto_item_add_subtree(unknown_item
, ett_unknown
[0]);
243 /*Add COL_INFO only if root element is IQ*/
244 if(strcmp(element
->name
,"iq")==0)
245 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "%s ", xmpp_ep_string_upcase(child
->name
));
247 if(child
->default_ns_abbrev
)
248 proto_item_append_text(unknown_item
,"(%s)",child
->default_ns_abbrev
);
250 xmpp_unknown_items(unknown_tree
, tvb
, pinfo
, child
, 1);
251 proto_item_append_text(unknown_item
, " [UNKNOWN]");
252 expert_add_info_format(pinfo
, unknown_item
, &ei_xmpp_unknown_element
, "Unknown element: %s", child
->name
);
254 childs
= childs
->next
;
259 xmpp_unknown_attrs(proto_tree
*tree
, tvbuff_t
*tvb
, packet_info
*pinfo _U_
, xmpp_element_t
*element
, gboolean displ_short_list
)
261 proto_item
*item
= proto_tree_get_parent(tree
);
263 GList
*keys
= g_hash_table_get_keys(element
->attrs
);
264 GList
*values
= g_hash_table_get_values(element
->attrs
);
266 GList
*keys_head
= keys
, *values_head
= values
;
268 gboolean short_list_started
= FALSE
;
270 while(keys
&& values
)
272 xmpp_attr_t
*attr
= (xmpp_attr_t
*) values
->data
;
273 if (!attr
->was_read
) {
274 if (displ_short_list
) {
275 if (!short_list_started
)
276 proto_item_append_text(item
, " [");
278 proto_item_append_text(item
, " ");
279 proto_item_append_text(item
, "%s=\"%s\"", (gchar
*) keys
->data
, attr
->value
);
281 short_list_started
= TRUE
;
284 /*If unknown element has xmlns attrib then header field hf_xmpp_xmlns is added to the tree.
285 In other case only text.*/
286 if (strcmp((const char *)keys
->data
, "xmlns") == 0)
287 proto_tree_add_string(tree
, hf_xmpp_xmlns
, tvb
, attr
->offset
, attr
->length
, attr
->value
);
289 /*xmlns may looks like xmlns:abbrev="sth"*/
290 gchar
* xmlns_needle
= epan_strcasestr((const char *)keys
->data
, "xmlns:");
291 if (xmlns_needle
&& xmlns_needle
== keys
->data
) {
292 proto_tree_add_string_format(tree
, hf_xmpp_xmlns
, tvb
, attr
->offset
, attr
->length
, attr
->value
,"%s: %s", (gchar
*)keys
->data
, attr
->value
);
294 proto_item
* unknown_attr_item
;
295 unknown_attr_item
= proto_tree_add_string_format(tree
,
296 hf_xmpp_unknown_attr
, tvb
, attr
->offset
, attr
->length
,
297 attr
->name
, "%s: %s", attr
->name
, attr
->value
);
298 proto_item_append_text(unknown_attr_item
, " [UNKNOWN ATTR]");
299 expert_add_info_format(pinfo
, unknown_attr_item
, &ei_xmpp_unknown_attribute
, "Unknown attribute %s", attr
->name
);
304 values
= values
->next
;
307 if(short_list_started
&& displ_short_list
)
308 proto_item_append_text(item
, "]");
310 g_list_free(keys_head
);
311 g_list_free(values_head
);
315 xmpp_cdata(proto_tree
*tree
, tvbuff_t
*tvb
, xmpp_element_t
*element
, gint hf
)
320 proto_tree_add_text(tree
, tvb
, element
->data
->offset
, element
->data
->length
, "CDATA: %s", element
->data
->value
);
322 proto_tree_add_string(tree
, hf
, tvb
, element
->data
->offset
, element
->data
->length
, element
->data
->value
);
327 proto_tree_add_text(tree
, tvb
, 0, 0, "CDATA: (empty)");
329 proto_tree_add_string(tree
, hf
, tvb
, 0, 0, "");
334 /* displays element that looks like <element_name>element_value</element_name>
335 * ELEMENT_NAME: element_value as TEXT(proto_tree_add_text) int PROTO_TREE
338 xmpp_simple_cdata_elem(proto_tree
*tree
, tvbuff_t
*tvb
, packet_info
*pinfo _U_
, xmpp_element_t
*element
)
340 proto_tree_add_text(tree
, tvb
, element
->offset
, element
->length
, "%s: %s", xmpp_ep_string_upcase(element
->name
), xmpp_elem_cdata(element
));
344 xmpp_ep_init_array_t(const gchar
** array
, gint len
)
346 xmpp_array_t
*result
;
348 result
= wmem_new(wmem_packet_scope(), xmpp_array_t
);
349 result
->data
= (gpointer
) array
;
350 result
->length
= len
;
356 xmpp_ep_init_attr_t(const gchar
*value
, gint offset
, gint length
)
359 result
= wmem_new(wmem_packet_scope(), xmpp_attr_t
);
360 result
->value
= value
;
361 result
->offset
= offset
;
362 result
->length
= length
;
369 xmpp_ep_string_upcase(const gchar
* string
)
371 gint len
= (int)strlen(string
);
373 gchar
* result
= (gchar
*)wmem_alloc0(wmem_packet_scope(), len
+1);
376 result
[i
] = string
[i
];
378 if(string
[i
]>='a' && string
[i
]<='z')
386 xmpp_element_t_cmp(gconstpointer a
, gconstpointer b
)
388 gint result
= strcmp(((xmpp_element_t
*)a
)->name
,((xmpp_element_t
*)b
)->name
);
390 if(result
== 0 && ((xmpp_element_t
*)a
)->was_read
)
397 xmpp_find_element_by_name(xmpp_element_t
*packet
,const gchar
*name
)
399 GList
*found_elements
;
400 xmpp_element_t
*search_element
;
402 /*create fake element only with name*/
403 search_element
= wmem_new(wmem_packet_scope(), xmpp_element_t
);
404 search_element
->name
= wmem_strdup(wmem_packet_scope(), name
);
406 found_elements
= g_list_find_custom(packet
->elements
, search_element
, xmpp_element_t_cmp
);
409 return found_elements
;
416 * function searches element in packet and sets it as read.
417 * if element doesn't exist, NULL is returned.
418 * If element is set as read, it is invisible for these functions.*/
420 xmpp_steal_element_by_name(xmpp_element_t
*packet
,const gchar
*name
)
423 xmpp_element_t
*element
= NULL
;
425 element_l
= xmpp_find_element_by_name(packet
, name
);
429 element
= (xmpp_element_t
*)element_l
->data
;
430 element
->was_read
= TRUE
;
438 xmpp_steal_element_by_names(xmpp_element_t
*packet
, const gchar
**names
, gint names_len
)
441 xmpp_element_t
*el
= NULL
;
443 for(i
= 0; i
<names_len
; i
++)
445 if((el
= xmpp_steal_element_by_name(packet
, names
[i
])))
453 xmpp_steal_element_by_attr(xmpp_element_t
*packet
, const gchar
*attr_name
, const gchar
*attr_value
)
455 GList
*childs
= packet
->elements
;
456 xmpp_element_t
*result
= NULL
;
459 xmpp_element_t
*child_elem
= (xmpp_element_t
*)childs
->data
;
460 xmpp_attr_t
*attr
= xmpp_get_attr(child_elem
, attr_name
);
463 attr
->was_read
= FALSE
;
465 if (!child_elem
->was_read
&& attr
&& strcmp(attr
->value
, attr_value
) == 0) {
467 result
= (xmpp_element_t
*)childs
->data
;
469 result
->was_read
= TRUE
;
473 childs
= childs
->next
;
480 xmpp_steal_element_by_name_and_attr(xmpp_element_t
*packet
, const gchar
*name
, const gchar
*attr_name
, const gchar
*attr_value
)
482 GList
*childs
= packet
->elements
;
483 xmpp_element_t
*result
= NULL
;
486 xmpp_element_t
*child_elem
= (xmpp_element_t
*)childs
->data
;
487 xmpp_attr_t
*attr
= xmpp_get_attr(child_elem
, attr_name
);
490 attr
->was_read
= FALSE
;
492 if (!child_elem
->was_read
&& attr
&& strcmp(child_elem
->name
, name
) == 0 && strcmp(attr
->value
, attr_value
) == 0) {
494 result
= (xmpp_element_t
*)childs
->data
;
496 result
->was_read
= TRUE
;
500 childs
= childs
->next
;
506 xmpp_get_first_element(xmpp_element_t
*packet
)
508 if(packet
->elements
&& packet
->elements
->data
)
509 return (xmpp_element_t
*)packet
->elements
->data
;
515 Function converts xml_frame_t structure to xmpp_element_t (simpler representation)
518 xmpp_xml_frame_to_element_t(xml_frame_t
*xml_frame
, xmpp_element_t
*parent
, tvbuff_t
*tvb
)
521 xmpp_element_t
*node
= wmem_new0(wmem_packet_scope(), xmpp_element_t
);
524 tvbparse_elem_t
* elem
;
526 node
->attrs
= g_hash_table_new(g_str_hash
, g_str_equal
);
527 node
->elements
= NULL
;
529 node
->was_read
= FALSE
;
530 node
->default_ns_abbrev
= NULL
;
532 node
->name
= wmem_strdup(wmem_packet_scope(), xml_frame
->name_orig_case
);
536 node
->namespaces
= g_hash_table_new(g_str_hash
, g_str_equal
);
539 xmpp_copy_hash_table(parent
->namespaces
, node
->namespaces
);
542 g_hash_table_insert(node
->namespaces
, (gpointer
)"", (gpointer
)"jabber:client");
545 if(xml_frame
->item
!= NULL
)
547 node
->length
= xml_frame
->item
->finfo
->length
;
550 node
->offset
= xml_frame
->start_offset
;
552 tt
= tvbparse_init(tvb
,node
->offset
,-1,NULL
,want_ignore
);
554 if((elem
= tvbparse_get(tt
,want_stream_end_with_ns
))!=NULL
)
556 node
->default_ns_abbrev
= tvb_get_string(wmem_packet_scope(), elem
->sub
->tvb
, elem
->sub
->offset
, elem
->sub
->len
);
559 child
= xml_frame
->first_child
;
563 if(child
->type
!= XML_FRAME_TAG
)
565 if(child
->type
== XML_FRAME_ATTRIB
)
569 gchar
*xmlns_needle
= NULL
;
571 xmpp_attr_t
*attr
= wmem_new(wmem_packet_scope(), xmpp_attr_t
);
574 attr
->was_read
= FALSE
;
576 if (child
->value
!= NULL
) {
577 l
= tvb_reported_length(child
->value
);
578 value
= (gchar
*)wmem_alloc0(wmem_packet_scope(), l
+ 1);
579 tvb_memcpy(child
->value
, value
, 0, l
);
584 attr
->length
= child
->item
->finfo
->length
;
587 attr
->offset
= child
->start_offset
;
589 attr
->name
= wmem_strdup(wmem_packet_scope(), child
->name_orig_case
);
591 g_hash_table_insert(node
->attrs
,(gpointer
)attr
->name
,(gpointer
)attr
);
593 /*checking that attr->name looks like xmlns:ns*/
594 xmlns_needle
= epan_strcasestr(attr
->name
, "xmlns");
596 if(xmlns_needle
== attr
->name
)
598 if(attr
->name
[5] == ':' && strlen(attr
->name
) > 6)
600 g_hash_table_insert(node
->namespaces
, (gpointer
)wmem_strdup(wmem_packet_scope(), &attr
->name
[6]), (gpointer
)wmem_strdup(wmem_packet_scope(), attr
->value
));
601 } else if(attr
->name
[5] == '\0')
603 g_hash_table_insert(node
->namespaces
, (gpointer
)"", (gpointer
)wmem_strdup(wmem_packet_scope(), attr
->value
));
609 else if( child
->type
== XML_FRAME_CDATA
)
611 xmpp_data_t
*data
= NULL
;
615 data
= wmem_new(wmem_packet_scope(), xmpp_data_t
);
619 if (child
->value
!= NULL
) {
620 l
= tvb_reported_length(child
->value
);
621 value
= (gchar
*)wmem_alloc0(wmem_packet_scope(), l
+ 1);
622 tvb_memcpy(child
->value
, value
, 0, l
);
629 data
->length
= child
->item
->finfo
->length
;
631 data
->offset
= child
->start_offset
;
636 node
->elements
= g_list_append(node
->elements
,(gpointer
)xmpp_xml_frame_to_element_t(child
, node
,tvb
));
639 child
= child
->next_sibling
;
645 xmpp_element_t_tree_free(xmpp_element_t
*root
)
647 GList
*childs
= root
->elements
;
649 g_hash_table_destroy(root
->attrs
);
650 g_hash_table_destroy(root
->namespaces
);
654 xmpp_element_t
*child
= (xmpp_element_t
*)childs
->data
;
656 xmpp_element_t_tree_free(child
);
657 childs
= childs
->next
;
659 g_list_free(root
->elements
);
662 /*Function recognize attribute names if they looks like xmlns:ns*/
664 attr_find_pred(gpointer key
, gpointer value _U_
, gpointer user_data
)
666 gchar
*attr_name
= (gchar
*) user_data
;
668 if( strcmp(attr_name
, "xmlns") == 0 )
670 gchar
*first_occur
= epan_strcasestr((const char *)key
, "xmlns:");
671 if(first_occur
&& first_occur
== key
)
679 /*Functions returns element's attibute by name and set as read*/
681 xmpp_get_attr(xmpp_element_t
*element
, const gchar
* attr_name
)
683 xmpp_attr_t
*result
= (xmpp_attr_t
*)g_hash_table_lookup(element
->attrs
, attr_name
);
687 result
= (xmpp_attr_t
*)g_hash_table_find(element
->attrs
, attr_find_pred
, (gpointer
)attr_name
);
691 result
->was_read
= TRUE
;
696 /*Functions returns element's attibute by name and namespace abbrev*/
698 xmpp_get_attr_ext(xmpp_element_t
*element
, const gchar
* attr_name
, const gchar
* ns_abbrev
)
700 gchar
* search_phrase
;
703 if(strcmp(ns_abbrev
,"")==0)
704 search_phrase
= wmem_strdup(wmem_packet_scope(), attr_name
);
705 else if(strcmp(attr_name
, "xmlns") == 0)
706 search_phrase
= wmem_strdup_printf(wmem_packet_scope(), "%s:%s",attr_name
, ns_abbrev
);
708 search_phrase
= wmem_strdup_printf(wmem_packet_scope(), "%s:%s", ns_abbrev
, attr_name
);
710 result
= (xmpp_attr_t
*)g_hash_table_lookup(element
->attrs
, search_phrase
);
714 result
= (xmpp_attr_t
*)g_hash_table_find(element
->attrs
, attr_find_pred
, (gpointer
)attr_name
);
718 result
->was_read
= TRUE
;
726 xmpp_element_to_string(tvbuff_t
*tvb
, xmpp_element_t
*element
)
730 if(tvb_offset_exists(tvb
, element
->offset
+element
->length
-1))
732 buff
= tvb_get_string(wmem_packet_scope(), tvb
, element
->offset
, element
->length
);
738 xmpp_attr_to_string(tvbuff_t
*tvb
, xmpp_attr_t
*attr
)
742 if(tvb_offset_exists(tvb
, attr
->offset
+ attr
->length
-1))
744 buff
= tvb_get_string(wmem_packet_scope(), tvb
, attr
->offset
, attr
->length
);
750 children_foreach_hide_func(proto_node
*node
, gpointer data
)
752 int *i
= (int *)data
;
754 PROTO_ITEM_SET_HIDDEN(node
);
759 children_foreach_show_func(proto_node
*node
, gpointer data
)
761 int *i
= (int *)data
;
763 PROTO_ITEM_SET_VISIBLE(node
);
768 xmpp_proto_tree_hide_first_child(proto_tree
*tree
)
771 proto_tree_children_foreach(tree
, children_foreach_hide_func
, &i
);
775 xmpp_proto_tree_show_first_child(proto_tree
*tree
)
778 proto_tree_children_foreach(tree
, children_foreach_show_func
, &i
);
782 proto_item_get_text(proto_item
*item
)
784 field_info
*fi
= NULL
;
790 fi
= PITEM_FINFO(item
);
799 result
= wmem_strdup(wmem_packet_scope(), fi
->rep
->representation
);
805 xmpp_display_attrs(proto_tree
*tree
, xmpp_element_t
*element
, packet_info
*pinfo
, tvbuff_t
*tvb
, xmpp_attr_info
*attrs
, guint n
)
807 proto_item
*item
= proto_tree_get_parent(tree
);
810 gboolean short_list_started
= FALSE
;
812 if(element
->default_ns_abbrev
)
813 proto_item_append_text(item
, "(%s)",element
->default_ns_abbrev
);
815 proto_item_append_text(item
," [");
816 for(i
= 0; i
< n
&& attrs
!=NULL
; i
++)
818 attr
= xmpp_get_attr(element
, attrs
[i
].name
);
821 if(attrs
[i
].hf
!= -1)
824 proto_tree_add_string_format(tree
, attrs
[i
].hf
, tvb
, attr
->offset
, attr
->length
, attr
->value
,"%s: %s", attr
->name
, attr
->value
);
826 proto_tree_add_string(tree
, attrs
[i
].hf
, tvb
, attr
->offset
, attr
->length
, attr
->value
);
830 proto_tree_add_text(tree
, tvb
, attr
->offset
, attr
->length
, "%s: %s", attr
->name
?attr
->name
:attrs
[i
].name
, attr
->value
);
833 if(attrs
[i
].in_short_list
)
835 if(short_list_started
)
837 proto_item_append_text(item
," ");
839 proto_item_append_text(item
,"%s=\"%s\"",attr
->name
?attr
->name
:attrs
[i
].name
, attr
->value
);
840 short_list_started
= TRUE
;
843 } else if(attrs
[i
].is_required
)
845 expert_add_info_format(pinfo
, item
, &ei_xmpp_required_attribute
, "Required attribute \"%s\" doesn't appear in \"%s\".", attrs
[i
].name
, element
->name
);
848 if(attrs
[i
].val_func
)
851 attrs
[i
].val_func(pinfo
, item
, attrs
[i
].name
, attr
->value
, attrs
[i
].data
);
853 attrs
[i
].val_func(pinfo
, item
, attrs
[i
].name
, NULL
, attrs
[i
].data
);
856 proto_item_append_text(item
,"]");
858 /*displays attributes that weren't recognized*/
859 xmpp_unknown_attrs(tree
, tvb
, pinfo
, element
, FALSE
);
863 xmpp_display_attrs_ext(proto_tree
*tree
, xmpp_element_t
*element
, packet_info
*pinfo
, tvbuff_t
*tvb
, xmpp_attr_info_ext
*attrs
, guint n
)
865 proto_item
*item
= proto_tree_get_parent(tree
);
868 gboolean short_list_started
= FALSE
;
870 GList
*ns_abbrevs_head
, *ns_abbrevs
= g_hash_table_get_keys(element
->namespaces
);
871 GList
*ns_fullnames_head
, *ns_fullnames
= g_hash_table_get_values(element
->namespaces
);
872 ns_abbrevs_head
= ns_abbrevs
;
873 ns_fullnames_head
= ns_fullnames
;
875 if(element
->default_ns_abbrev
)
876 proto_item_append_text(item
, "(%s)",element
->default_ns_abbrev
);
878 proto_item_append_text(item
," [");
879 while(ns_abbrevs
&& ns_fullnames
)
881 for (i
= 0; i
< n
&& attrs
!= NULL
; i
++) {
882 if(strcmp((const char *)(ns_fullnames
->data
), attrs
[i
].ns
) == 0)
884 attr
= xmpp_get_attr_ext(element
, attrs
[i
].info
.name
, (const gchar
*)(ns_abbrevs
->data
));
885 if(!attr
&& element
->default_ns_abbrev
&& strcmp((const char *)ns_abbrevs
->data
, element
->default_ns_abbrev
)==0)
886 attr
= xmpp_get_attr_ext(element
, attrs
[i
].info
.name
, "");
889 if (attrs
[i
].info
.hf
!= -1) {
891 proto_tree_add_string_format(tree
, attrs
[i
].info
.hf
, tvb
, attr
->offset
, attr
->length
, attr
->value
, "%s: %s", attr
->name
, attr
->value
);
893 proto_tree_add_string(tree
, attrs
[i
].info
.hf
, tvb
, attr
->offset
, attr
->length
, attr
->value
);
895 proto_tree_add_text(tree
, tvb
, attr
->offset
, attr
->length
, "%s: %s", attr
->name
? attr
->name
: attrs
[i
].info
.name
, attr
->value
);
898 if (attrs
[i
].info
.in_short_list
) {
899 if (short_list_started
) {
900 proto_item_append_text(item
, " ");
902 proto_item_append_text(item
, "%s=\"%s\"", attr
->name
? attr
->name
: attrs
[i
].info
.name
, attr
->value
);
903 short_list_started
= TRUE
;
906 } else if (attrs
[i
].info
.is_required
) {
907 expert_add_info_format(pinfo
, item
, &ei_xmpp_required_attribute
, "Required attribute \"%s\" doesn't appear in \"%s\".", attrs
[i
].info
.name
, element
->name
);
910 if (attrs
[i
].info
.val_func
) {
912 attrs
[i
].info
.val_func(pinfo
, item
, attrs
[i
].info
.name
, attr
->value
, attrs
[i
].info
.data
);
914 attrs
[i
].info
.val_func(pinfo
, item
, attrs
[i
].info
.name
, NULL
, attrs
[i
].info
.data
);
918 ns_abbrevs
= ns_abbrevs
->next
;
919 ns_fullnames
= ns_fullnames
->next
;
921 proto_item_append_text(item
,"]");
923 /*displays attributes that weren't recognized*/
924 xmpp_unknown_attrs(tree
, tvb
, pinfo
, element
, FALSE
);
926 g_list_free(ns_abbrevs_head
);
927 g_list_free(ns_fullnames_head
);
930 typedef struct _name_attr_t
933 const gchar
*attr_name
;
934 const gchar
*attr_value
;
938 returns pointer to the struct that contains 3 strings(element name, attribute name, attribute value)
941 xmpp_name_attr_struct(const gchar
*name
, const gchar
*attr_name
, const gchar
*attr_value
)
945 result
= wmem_new(wmem_packet_scope(), name_attr_t
);
947 result
->attr_name
= attr_name
;
948 result
->attr_value
= attr_value
;
953 xmpp_display_elems(proto_tree
*tree
, xmpp_element_t
*parent
, packet_info
*pinfo
, tvbuff_t
*tvb
, xmpp_elem_info
*elems
, guint n
)
957 for(i
= 0; i
< n
&& elems
!=NULL
; i
++)
959 xmpp_element_t
*elem
= NULL
;
961 if(elems
[i
].type
== NAME_AND_ATTR
)
963 gboolean loop
= TRUE
;
965 name_attr_t
*a
= (name_attr_t
*)(elems
[i
].data
);
967 while(loop
&& (elem
= xmpp_steal_element_by_name_and_attr(parent
, a
->name
, a
->attr_name
, a
->attr_value
))!=NULL
)
969 elems
[i
].elem_func(tree
, tvb
, pinfo
, elem
);
970 if(elems
[i
].occurrence
== ONE
)
973 } else if(elems
[i
].type
== NAME
)
975 gboolean loop
= TRUE
;
976 const gchar
*name
= (const gchar
*)(elems
[i
].data
);
978 while(loop
&& (elem
= xmpp_steal_element_by_name(parent
, name
))!=NULL
)
980 elems
[i
].elem_func(tree
, tvb
, pinfo
, elem
);
981 if(elems
[i
].occurrence
== ONE
)
985 else if(elems
[i
].type
== ATTR
)
987 gboolean loop
= TRUE
;
988 name_attr_t
*attr
= (name_attr_t
*)(elems
[i
].data
);
990 while(loop
&& (elem
= xmpp_steal_element_by_attr(parent
, attr
->attr_name
, attr
->attr_value
))!=NULL
)
992 elems
[i
].elem_func(tree
, tvb
, pinfo
, elem
);
993 if(elems
[i
].occurrence
== ONE
)
997 } else if(elems
[i
].type
== NAMES
)
999 gboolean loop
= TRUE
;
1000 const xmpp_array_t
*names
= (const xmpp_array_t
*)(elems
[i
].data
);
1002 while(loop
&& (elem
= xmpp_steal_element_by_names(parent
, (const gchar
**)names
->data
, names
->length
))!=NULL
)
1004 elems
[i
].elem_func(tree
, tvb
, pinfo
, elem
);
1005 if(elems
[i
].occurrence
== ONE
)
1011 xmpp_unknown(tree
, tvb
, pinfo
, parent
);
1015 function checks that variable value is in array ((xmpp_array_t)data)->data
1018 xmpp_val_enum_list(packet_info
*pinfo
, proto_item
*item
, const gchar
*name
, const gchar
*value
, gconstpointer data
)
1020 const xmpp_array_t
*enums_array
= (const xmpp_array_t
*)data
;
1023 gboolean value_in_enums
= FALSE
;
1025 gchar
**enums
= (char**)enums_array
->data
;
1027 if (value
!= NULL
) {
1028 for (i
= 0; i
< enums_array
->length
; i
++) {
1029 if (strcmp(value
, enums
[i
]) == 0) {
1030 value_in_enums
= TRUE
;
1034 if (!value_in_enums
) {
1035 expert_add_info_format(pinfo
, item
, &ei_xmpp_field_unexpected_value
, "Field \"%s\" has unexpected value \"%s\"", name
, value
);
1042 xmpp_change_elem_to_attrib(const gchar
*elem_name
, const gchar
*attr_name
, xmpp_element_t
*parent
, xmpp_attr_t
* (*transform_func
)(xmpp_element_t
*element
))
1044 xmpp_element_t
*element
= NULL
;
1045 xmpp_attr_t
*fake_attr
= NULL
;
1047 element
= xmpp_steal_element_by_name(parent
, elem_name
);
1049 fake_attr
= transform_func(element
);
1052 g_hash_table_insert(parent
->attrs
, (gpointer
)attr_name
, fake_attr
);
1056 xmpp_transform_func_cdata(xmpp_element_t
*elem
)
1058 xmpp_attr_t
*result
= xmpp_ep_init_attr_t(elem
->data
?elem
->data
->value
:"", elem
->offset
, elem
->length
);
1063 xmpp_copy_hash_table_func(gpointer key
, gpointer value
, gpointer user_data
)
1065 GHashTable
*dst
= (GHashTable
*)user_data
;
1066 g_hash_table_insert(dst
, key
, value
);
1069 void xmpp_copy_hash_table(GHashTable
*src
, GHashTable
*dst
)
1071 g_hash_table_foreach(src
, xmpp_copy_hash_table_func
, dst
);
1076 printf_hash_table_func(gpointer key
, gpointer value
, gpointer user_data _U_
)
1078 printf("'%s' '%s'\n", (gchar
*)key
, (gchar
*)value
);
1082 printf_elements(xmpp_element_t
*root
)
1084 GList
*elems
= root
->elements
;
1086 printf("%s\n", root
->name
);
1087 g_hash_table_foreach(root
->namespaces
, printf_hash_table_func
, NULL
);
1090 printf_elements(elems
->data
);
1091 elems
= elems
->next
;
1097 * Editor modelines - http://www.wireshark.org/tools/modelines.html
1102 * indent-tabs-mode: nil
1105 * ex: set shiftwidth=4 tabstop=8 expandtab:
1106 * :indentSize=4:tabSize=8:noTabs=true: