FIXUP: WIP: verification_trailer
[wireshark-wip.git] / epan / dissectors / packet-xmpp-utils.c
blob564d21489c06a19ecc5b6aaa3523786618d36d66
1 /* xmpp-utils.c
2 * Wireshark's XMPP dissector.
4 * Copyright 2011, Mariusz Okroj <okrojmariusz[]gmail.com>
6 * $Id$
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.
27 #include "config.h"
29 #include <glib.h>
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>
43 void
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;
48 xmpp_attr_t *attr_id;
49 char *id;
51 attr_id = xmpp_get_attr(packet, "id");
53 if (!attr_id) {
54 return;
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);
61 if (xmpp_trans) {
62 xmpp_trans->resp_frame = pinfo->fd->num;
64 } else {
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);
75 } else {
76 wmem_tree_lookup_string(xmpp_info->req_resp, id, EMEM_TREE_STRING_NOCASE);
80 void
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) {
90 xmpp_attr_t *attr_id;
91 xmpp_attr_t *attr_sid;
93 char *se_id;
94 char *se_sid;
97 attr_id = xmpp_get_attr(packet, "id");
98 if (!attr_id) {
99 return;
102 attr_sid = xmpp_get_attr(jingle_packet, "sid");
103 if (!attr_sid) {
104 return;
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);
114 void
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;
128 char *se_id;
129 char *se_sid;
131 xmpp_attr_t *xmlns = xmpp_get_attr(gtalk_packet, "xmlns");
132 if(xmlns && strcmp(xmlns->value,"http://www.google.com/session") != 0)
133 return;
135 attr_id = xmpp_get_attr(packet, "id");
136 if (!attr_id) {
137 return;
140 attr_sid = xmpp_get_attr(gtalk_packet, "id");
141 if (!attr_sid) {
142 return;
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);
152 void
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;
156 GList *ibb_packet_l;
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");
167 if(!ibb_packet_l)
168 ibb_packet_l = xmpp_find_element_by_name(packet,"close");
169 if(!ibb_packet_l)
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;
179 char *se_id;
180 char *se_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);
194 static void
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);
203 if(element->data)
205 proto_tree_add_text(tree, tvb, element->data->offset, element->data->length, "CDATA: %s",element->data->value);
208 while(childs)
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;
223 void
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*/
229 while(childs)
231 xmpp_element_t *child = (xmpp_element_t *)childs->data;
232 if(!child->was_read)
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;
258 void
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, " [");
277 else
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);
288 else {
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);
293 } else {
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);
303 keys = keys->next;
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);
314 void
315 xmpp_cdata(proto_tree *tree, tvbuff_t *tvb, xmpp_element_t *element, gint hf)
317 if(element->data)
319 if (hf == -1) {
320 proto_tree_add_text(tree, tvb, element->data->offset, element->data->length, "CDATA: %s", element->data->value);
321 } else {
322 proto_tree_add_string(tree, hf, tvb, element->data->offset, element->data->length, element->data->value);
324 } else
326 if (hf == -1) {
327 proto_tree_add_text(tree, tvb, 0, 0, "CDATA: (empty)");
328 } else {
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
337 void
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));
343 xmpp_array_t*
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;
352 return result;
355 xmpp_attr_t*
356 xmpp_ep_init_attr_t(const gchar *value, gint offset, gint length)
358 xmpp_attr_t *result;
359 result = wmem_new(wmem_packet_scope(), xmpp_attr_t);
360 result->value = value;
361 result->offset = offset;
362 result->length = length;
363 result->name = NULL;
365 return result;
368 gchar*
369 xmpp_ep_string_upcase(const gchar* string)
371 gint len = (int)strlen(string);
372 gint i;
373 gchar* result = (gchar *)wmem_alloc0(wmem_packet_scope(), len+1);
374 for(i=0; i<len; i++)
376 result[i] = string[i];
378 if(string[i]>='a' && string[i]<='z')
379 result[i]-='a'-'A';
382 return result;
385 gint
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)
391 result = -1;
393 return result;
396 GList*
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);
408 if(found_elements)
409 return found_elements;
410 else
411 return NULL;
415 /* steal_*
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.*/
419 xmpp_element_t*
420 xmpp_steal_element_by_name(xmpp_element_t *packet,const gchar *name)
422 GList *element_l;
423 xmpp_element_t *element = NULL;
425 element_l = xmpp_find_element_by_name(packet, name);
427 if(element_l)
429 element = (xmpp_element_t *)element_l->data;
430 element->was_read = TRUE;
433 return element;
437 xmpp_element_t*
438 xmpp_steal_element_by_names(xmpp_element_t *packet, const gchar **names, gint names_len)
440 gint i;
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])))
446 break;
449 return el;
452 xmpp_element_t*
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;
458 while (childs) {
459 xmpp_element_t *child_elem = (xmpp_element_t *)childs->data;
460 xmpp_attr_t *attr = xmpp_get_attr(child_elem, attr_name);
462 if(attr)
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;
471 break;
472 } else
473 childs = childs->next;
476 return result;
479 xmpp_element_t*
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;
485 while (childs) {
486 xmpp_element_t *child_elem = (xmpp_element_t *)childs->data;
487 xmpp_attr_t *attr = xmpp_get_attr(child_elem, attr_name);
489 if(attr)
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;
498 break;
499 } else
500 childs = childs->next;
502 return result;
505 xmpp_element_t*
506 xmpp_get_first_element(xmpp_element_t *packet)
508 if(packet->elements && packet->elements->data)
509 return (xmpp_element_t *)packet->elements->data;
510 else
511 return NULL;
515 Function converts xml_frame_t structure to xmpp_element_t (simpler representation)
517 xmpp_element_t*
518 xmpp_xml_frame_to_element_t(xml_frame_t *xml_frame, xmpp_element_t *parent, tvbuff_t *tvb)
520 xml_frame_t *child;
521 xmpp_element_t *node = wmem_new0(wmem_packet_scope(), xmpp_element_t);
523 tvbparse_t* tt;
524 tvbparse_elem_t* elem;
526 node->attrs = g_hash_table_new(g_str_hash, g_str_equal);
527 node->elements = NULL;
528 node->data = 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);
533 node->offset = 0;
534 node->length = 0;
536 node->namespaces = g_hash_table_new(g_str_hash, g_str_equal);
537 if(parent)
539 xmpp_copy_hash_table(parent->namespaces, node->namespaces);
540 } else
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;
561 while(child)
563 if(child->type != XML_FRAME_TAG)
565 if(child->type == XML_FRAME_ATTRIB)
567 gint l;
568 gchar *value = NULL;
569 gchar *xmlns_needle = NULL;
571 xmpp_attr_t *attr = wmem_new(wmem_packet_scope(), xmpp_attr_t);
572 attr->length = 0;
573 attr->offset = 0;
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);
582 if(child->item)
584 attr->length = child->item->finfo->length;
587 attr->offset = child->start_offset;
588 attr->value = value;
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;
612 gint l;
613 gchar* value = NULL;
615 data = wmem_new(wmem_packet_scope(), xmpp_data_t);
616 data->length = 0;
617 data->offset = 0;
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);
625 data->value = value;
627 if(child->item)
629 data->length = child->item->finfo->length;
631 data->offset = child->start_offset;
632 node->data = data;
634 } else
636 node->elements = g_list_append(node->elements,(gpointer)xmpp_xml_frame_to_element_t(child, node,tvb));
639 child = child->next_sibling;
641 return node;
644 void
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);
652 while(childs)
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*/
663 static gboolean
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)
672 return TRUE;
673 else
674 return FALSE;
676 return FALSE;
679 /*Functions returns element's attibute by name and set as read*/
680 xmpp_attr_t*
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);
685 if(!result)
687 result = (xmpp_attr_t *)g_hash_table_find(element->attrs, attr_find_pred, (gpointer)attr_name);
690 if(result)
691 result->was_read = TRUE;
693 return result;
696 /*Functions returns element's attibute by name and namespace abbrev*/
697 static xmpp_attr_t*
698 xmpp_get_attr_ext(xmpp_element_t *element, const gchar* attr_name, const gchar* ns_abbrev)
700 gchar* search_phrase;
701 xmpp_attr_t *result;
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);
707 else
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);
712 if(!result)
714 result = (xmpp_attr_t *)g_hash_table_find(element->attrs, attr_find_pred, (gpointer)attr_name);
717 if(result)
718 result->was_read = TRUE;
720 return result;
725 gchar*
726 xmpp_element_to_string(tvbuff_t *tvb, xmpp_element_t *element)
728 gchar *buff = NULL;
730 if(tvb_offset_exists(tvb, element->offset+element->length-1))
732 buff = tvb_get_string(wmem_packet_scope(), tvb, element->offset, element->length);
734 return buff;
737 gchar*
738 xmpp_attr_to_string(tvbuff_t *tvb, xmpp_attr_t *attr)
740 gchar *buff = NULL;
742 if(tvb_offset_exists(tvb, attr->offset + attr->length-1))
744 buff = tvb_get_string(wmem_packet_scope(), tvb, attr->offset, attr->length);
746 return buff;
749 static void
750 children_foreach_hide_func(proto_node *node, gpointer data)
752 int *i = (int *)data;
753 if((*i) == 0)
754 PROTO_ITEM_SET_HIDDEN(node);
755 (*i)++;
758 static void
759 children_foreach_show_func(proto_node *node, gpointer data)
761 int *i = (int *)data;
762 if((*i) == 0)
763 PROTO_ITEM_SET_VISIBLE(node);
764 (*i)++;
767 void
768 xmpp_proto_tree_hide_first_child(proto_tree *tree)
770 int i = 0;
771 proto_tree_children_foreach(tree, children_foreach_hide_func, &i);
774 void
775 xmpp_proto_tree_show_first_child(proto_tree *tree)
777 int i = 0;
778 proto_tree_children_foreach(tree, children_foreach_show_func, &i);
781 gchar*
782 proto_item_get_text(proto_item *item)
784 field_info *fi = NULL;
785 gchar *result;
787 if(item == NULL)
788 return NULL;
790 fi = PITEM_FINFO(item);
792 if(fi==NULL)
793 return NULL;
795 if (fi->rep == NULL)
796 return NULL;
799 result = wmem_strdup(wmem_packet_scope(), fi->rep->representation);
800 return result;
804 void
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);
808 xmpp_attr_t *attr;
809 guint i;
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);
819 if(attr)
821 if(attrs[i].hf != -1)
823 if(attr->name)
824 proto_tree_add_string_format(tree, attrs[i].hf, tvb, attr->offset, attr->length, attr->value,"%s: %s", attr->name, attr->value);
825 else
826 proto_tree_add_string(tree, attrs[i].hf, tvb, attr->offset, attr->length, attr->value);
828 else
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)
850 if(attr)
851 attrs[i].val_func(pinfo, item, attrs[i].name, attr->value, attrs[i].data);
852 else
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);
862 void
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);
866 xmpp_attr_t *attr;
867 guint i;
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, "");
888 if (attr) {
889 if (attrs[i].info.hf != -1) {
890 if (attr->name)
891 proto_tree_add_string_format(tree, attrs[i].info.hf, tvb, attr->offset, attr->length, attr->value, "%s: %s", attr->name, attr->value);
892 else
893 proto_tree_add_string(tree, attrs[i].info.hf, tvb, attr->offset, attr->length, attr->value);
894 } else {
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) {
911 if (attr)
912 attrs[i].info.val_func(pinfo, item, attrs[i].info.name, attr->value, attrs[i].info.data);
913 else
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
932 const gchar *name;
933 const gchar *attr_name;
934 const gchar *attr_value;
935 } name_attr_t;
938 returns pointer to the struct that contains 3 strings(element name, attribute name, attribute value)
940 gpointer
941 xmpp_name_attr_struct(const gchar *name, const gchar *attr_name, const gchar *attr_value)
943 name_attr_t *result;
945 result = wmem_new(wmem_packet_scope(), name_attr_t);
946 result->name = name;
947 result->attr_name = attr_name;
948 result->attr_value = attr_value;
949 return result;
952 void
953 xmpp_display_elems(proto_tree *tree, xmpp_element_t *parent, packet_info *pinfo, tvbuff_t *tvb, xmpp_elem_info *elems, guint n)
955 guint i;
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)
971 loop = FALSE;
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)
982 loop = FALSE;
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)
994 loop = FALSE;
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)
1006 loop = FALSE;
1011 xmpp_unknown(tree, tvb, pinfo, parent);
1015 function checks that variable value is in array ((xmpp_array_t)data)->data
1017 void
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;
1022 gint i;
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;
1031 break;
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);
1041 void
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);
1048 if(element)
1049 fake_attr = transform_func(element);
1051 if(fake_attr)
1052 g_hash_table_insert(parent->attrs, (gpointer)attr_name, fake_attr);
1055 xmpp_attr_t*
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);
1059 return result;
1062 static void
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);
1074 #if 0
1075 static void
1076 printf_hash_table_func(gpointer key, gpointer value, gpointer user_data _U_)
1078 printf("'%s' '%s'\n", (gchar*)key, (gchar*)value);
1081 void
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);
1088 while(elems)
1090 printf_elements(elems->data);
1091 elems = elems->next;
1094 #endif
1097 * Editor modelines - http://www.wireshark.org/tools/modelines.html
1099 * Local variables:
1100 * c-basic-offset: 4
1101 * tab-width: 8
1102 * indent-tabs-mode: nil
1103 * End:
1105 * ex: set shiftwidth=4 tabstop=8 expandtab:
1106 * :indentSize=4:tabSize=8:noTabs=true: