MSWSP: fix dissect_mswsp_smb()
[wireshark-wip.git] / epan / dissectors / packet-xml.c
blob4e34e991d9407bc1a26c544e12fc67f5b1843bec
1 /* packet-xml.c
2 * wireshark's xml dissector .
4 * (C) 2005, Luis E. Garcia Ontanon.
6 * $Id$
8 * Refer to the AUTHORS file or the AUTHORS section in the man page
9 * for contacting the author(s) of this file.
11 * Wireshark - Network traffic analyzer
12 * By Gerald Combs <gerald@wireshark.org>
13 * Copyright 1998 Gerald Combs
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version 2
18 * of the License, or (at your option) any later version.
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
30 #include "config.h"
32 #ifdef HAVE_DIRENT_H
33 #include <dirent.h>
34 #endif
36 #include <string.h>
37 #include <errno.h>
39 #include <glib.h>
41 #include <wsutil/str_util.h>
42 #include <wsutil/report_err.h>
44 #include <epan/wmem/wmem.h>
45 #include <epan/packet.h>
46 #include <epan/tvbparse.h>
47 #include <epan/dtd.h>
48 #include <epan/filesystem.h>
49 #include <epan/prefs.h>
50 #include <epan/garrayfix.h>
52 #include "packet-xml.h"
54 struct _attr_reg_data {
55 wmem_array_t *hf;
56 const gchar *basename;
60 static gint ett_dtd = -1;
61 static gint ett_xmpli = -1;
63 static int hf_unknowwn_attrib = -1;
64 static int hf_comment = -1;
65 static int hf_xmlpi = -1;
66 static int hf_dtd_tag = -1;
67 static int hf_doctype = -1;
69 /* dissector handles */
70 static dissector_handle_t xml_handle;
72 /* parser definitions */
73 static tvbparse_wanted_t *want;
74 static tvbparse_wanted_t *want_ignore;
75 static tvbparse_wanted_t *want_heur;
77 static GHashTable *xmpli_names;
78 static GHashTable *media_types;
80 static xml_ns_t xml_ns = {(gchar *)"xml", "/", -1, -1, -1, NULL, NULL, NULL};
81 static xml_ns_t unknown_ns = {(gchar *)"unknown", "?", -1, -1, -1, NULL, NULL, NULL};
82 static xml_ns_t *root_ns;
84 static gboolean pref_heuristic_media = FALSE;
85 static gboolean pref_heuristic_tcp = FALSE;
86 static gboolean pref_heuristic_udp = FALSE;
87 static gboolean pref_heuristic_media_save = FALSE;
88 static gboolean pref_heuristic_tcp_save = FALSE;
89 static gboolean pref_heuristic_udp_save = FALSE;
90 static gboolean pref_heuristic_unicode = FALSE;
92 static range_t *global_xml_tcp_range = NULL;
93 static range_t *xml_tcp_range = NULL;
96 #define XML_CDATA -1000
97 #define XML_SCOPED_NAME -1001
100 static wmem_array_t *hf_arr;
101 static GArray *ett_arr;
103 static const gchar *default_media_types[] = {
104 "text/xml",
105 "text/vnd.wap.wml",
106 "text/vnd.wap.si",
107 "text/vnd.wap.sl",
108 "text/vnd.wap.co",
109 "text/vnd.wap.emn",
110 "application/auth-policy+xml",
111 "application/ccmp+xml",
112 "application/cpim-pidf+xml",
113 "application/cpl+xml",
114 "application/mathml+xml",
115 "application/media_control+xml",
116 "application/note+xml",
117 "application/pidf+xml",
118 "application/poc-settings+xml",
119 "application/rdf+xml",
120 "application/reginfo+xml",
121 "application/resource-lists+xml",
122 "application/rlmi+xml",
123 "application/rls-services+xml",
124 "application/rss+xml",
125 "application/smil",
126 "application/simple-filter+xml",
127 "application/simservs+xml",
128 "application/soap+xml",
129 "application/vnd.etsi.aoc+xml",
130 "application/vnd.etsi.cug+xml",
131 "application/vnd.etsi.iptvcommand+xml",
132 "application/vnd.etsi.iptvdiscovery+xml",
133 "application/vnd.etsi.iptvprofile+xml",
134 "application/vnd.etsi.iptvsad-bc+xml",
135 "application/vnd.etsi.iptvsad-cod+xml",
136 "application/vnd.etsi.iptvsad-npvr+xml",
137 "application/vnd.etsi.iptvueprofile+xml",
138 "application/vnd.etsi.mcid+xml",
139 "application/vnd.etsi.sci+xml",
140 "application/vnd.etsi.simservs+xml",
141 "application/vnd.3gpp.cw+xml",
142 "application/vnd.3gpp.SRVCC-info+xml",
143 "application/vnd.wv.csp+xml",
144 "application/vnd.wv.csp.xml",
145 "application/watcherinfo+xml",
146 "application/xcap-att+xml",
147 "application/xcap-caps+xml",
148 "application/xcap-diff+xml",
149 "application/xcap-el+xml",
150 "application/xcap-error+xml",
151 "application/xcap-ns+xml",
152 "application/xml",
153 "application/xml-dtd",
154 "application/xpidf+xml",
155 "application/xslt+xml",
156 "application/x-wms-logconnectstats",
157 "application/x-wms-logplaystats",
158 "application/x-wms-sendevent",
159 "image/svg+xml",
162 static void insert_xml_frame(xml_frame_t *parent, xml_frame_t *new_child)
164 new_child->first_child = NULL;
165 new_child->last_child = NULL;
167 new_child->parent = parent;
168 new_child->next_sibling = NULL;
169 new_child->prev_sibling = NULL;
170 if (parent == NULL) return; /* root */
172 if (parent->first_child == NULL) { /* the 1st child */
173 parent->first_child = new_child;
174 } else { /* following children */
175 parent->last_child->next_sibling = new_child;
176 new_child->prev_sibling = parent->last_child;
178 parent->last_child = new_child;
181 static void
182 dissect_xml(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
184 tvbparse_t *tt;
185 static GPtrArray *stack;
186 xml_frame_t *current_frame;
187 const char *colinfo_str;
189 if (stack != NULL)
190 g_ptr_array_free(stack, TRUE);
192 stack = g_ptr_array_new();
193 current_frame = (xml_frame_t *)wmem_alloc(wmem_packet_scope(), sizeof(xml_frame_t));
194 current_frame->type = XML_FRAME_ROOT;
195 current_frame->name = NULL;
196 current_frame->name_orig_case = NULL;
197 current_frame->value = NULL;
198 insert_xml_frame(NULL, current_frame);
199 g_ptr_array_add(stack, current_frame);
201 tt = tvbparse_init(tvb, 0, -1, stack, want_ignore);
202 current_frame->start_offset = 0;
204 root_ns = NULL;
206 if (pinfo->match_string)
207 root_ns = (xml_ns_t *)g_hash_table_lookup(media_types, pinfo->match_string);
209 if (! root_ns ) {
210 root_ns = &xml_ns;
211 colinfo_str = "/XML";
212 } else {
213 char *colinfo_str_buf;
214 colinfo_str_buf = wmem_strdup_printf(wmem_packet_scope(), "/%s", root_ns->name);
215 ascii_strup_inplace(colinfo_str_buf);
216 colinfo_str = colinfo_str_buf;
219 col_append_str(pinfo->cinfo, COL_PROTOCOL, colinfo_str);
221 current_frame->ns = root_ns;
223 current_frame->item = proto_tree_add_item(tree, current_frame->ns->hf_tag, tvb, 0, -1, ENC_UTF_8|ENC_NA);
224 current_frame->tree = proto_item_add_subtree(current_frame->item, current_frame->ns->ett);
225 current_frame->last_item = current_frame->item;
227 while(tvbparse_get(tt, want)) ;
229 pinfo->private_data = current_frame; /* pass XML structure to the dissector calling XML */
232 static gboolean dissect_xml_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
234 if (tvbparse_peek(tvbparse_init(tvb, 0, -1, NULL, want_ignore), want_heur)) {
235 dissect_xml(tvb, pinfo, tree);
236 return TRUE;
237 } else if (pref_heuristic_unicode) {
238 const guint8 *data_str = tvb_get_unicode_string(NULL, tvb, 0, tvb_length(tvb), ENC_LITTLE_ENDIAN);
239 tvbuff_t *unicode_tvb = tvb_new_child_real_data(tvb, data_str, tvb_length(tvb)/2, tvb_length(tvb)/2);
240 tvb_set_free_cb(unicode_tvb, g_free);
241 if (tvbparse_peek(tvbparse_init(unicode_tvb, 0, -1, NULL, want_ignore), want_heur)) {
242 add_new_data_source(pinfo, unicode_tvb, "UTF8");
243 dissect_xml(unicode_tvb, pinfo, tree);
244 return TRUE;
247 return FALSE;
250 xml_frame_t *xml_get_tag(xml_frame_t *frame, const gchar *name)
252 xml_frame_t *tag = NULL;
254 xml_frame_t *xml_item = frame->first_child;
255 while (xml_item) {
256 if (xml_item->type == XML_FRAME_TAG) {
257 if (!name) { /* get the 1st tag */
258 tag = xml_item;
259 break;
260 } else if (xml_item->name_orig_case && !strcmp(xml_item->name_orig_case, name)) {
261 tag = xml_item;
262 break;
265 xml_item = xml_item->next_sibling;
268 return tag;
271 xml_frame_t *xml_get_attrib(xml_frame_t *frame, const gchar *name)
273 xml_frame_t *attr = NULL;
275 xml_frame_t *xml_item = frame->first_child;
276 while (xml_item) {
277 if ((xml_item->type == XML_FRAME_ATTRIB) &&
278 xml_item->name_orig_case && !strcmp(xml_item->name_orig_case, name)) {
279 attr = xml_item;
280 break;
282 xml_item = xml_item->next_sibling;
285 return attr;
288 xml_frame_t *xml_get_cdata(xml_frame_t *frame)
290 xml_frame_t *cdata = NULL;
292 xml_frame_t *xml_item = frame->first_child;
293 while (xml_item) {
294 if (xml_item->type == XML_FRAME_CDATA) {
295 cdata = xml_item;
296 break;
298 xml_item = xml_item->next_sibling;
301 return cdata;
304 static void after_token(void *tvbparse_data, const void *wanted_data _U_, tvbparse_elem_t *tok)
306 GPtrArray *stack = (GPtrArray *)tvbparse_data;
307 xml_frame_t *current_frame = (xml_frame_t *)g_ptr_array_index(stack, stack->len - 1);
308 int hfid;
309 gboolean is_cdata = FALSE;
310 proto_item *pi;
311 xml_frame_t *new_frame;
313 if (tok->id == XML_CDATA) {
314 hfid = current_frame->ns ? current_frame->ns->hf_cdata : xml_ns.hf_cdata;
315 is_cdata = TRUE;
316 } else if ( tok->id > 0) {
317 hfid = tok->id;
318 } else {
319 hfid = xml_ns.hf_cdata;
322 pi = proto_tree_add_item(current_frame->tree, hfid, tok->tvb, tok->offset, tok->len, ENC_UTF_8|ENC_NA);
324 proto_item_set_text(pi, "%s",
325 tvb_format_text(tok->tvb, tok->offset, tok->len));
327 if (is_cdata) {
328 new_frame = (xml_frame_t *)wmem_alloc(wmem_packet_scope(), sizeof(xml_frame_t));
329 new_frame->type = XML_FRAME_CDATA;
330 new_frame->name = NULL;
331 new_frame->name_orig_case = NULL;
332 new_frame->value = tvb_new_subset(tok->tvb, tok->offset, tok->len, tok->len);
333 insert_xml_frame(current_frame, new_frame);
334 new_frame->item = pi;
335 new_frame->last_item = pi;
336 new_frame->tree = NULL;
337 new_frame->start_offset = tok->offset;
338 new_frame->ns = NULL;
342 static void before_xmpli(void *tvbparse_data, const void *wanted_data _U_, tvbparse_elem_t *tok)
344 GPtrArray *stack = (GPtrArray *)tvbparse_data;
345 xml_frame_t *current_frame = (xml_frame_t *)g_ptr_array_index(stack, stack->len - 1);
346 proto_item *pi;
347 proto_tree *pt;
348 tvbparse_elem_t *name_tok = tok->sub->next;
349 gchar *name = tvb_get_string(wmem_packet_scope(), name_tok->tvb, name_tok->offset, name_tok->len);
350 xml_ns_t *ns = (xml_ns_t *)g_hash_table_lookup(xmpli_names, name);
351 xml_frame_t *new_frame;
353 int hf_tag;
354 gint ett;
356 ascii_strdown_inplace(name);
357 if (!ns) {
358 hf_tag = hf_xmlpi;
359 ett = ett_xmpli;
360 } else {
361 hf_tag = ns->hf_tag;
362 ett = ns->ett;
365 pi = proto_tree_add_item(current_frame->tree, hf_tag, tok->tvb, tok->offset, tok->len, ENC_UTF_8|ENC_NA);
367 proto_item_set_text(pi, "%s", tvb_format_text(tok->tvb, tok->offset, (name_tok->offset - tok->offset) + name_tok->len));
369 pt = proto_item_add_subtree(pi, ett);
371 new_frame = (xml_frame_t *)wmem_alloc(wmem_packet_scope(), sizeof(xml_frame_t));
372 new_frame->type = XML_FRAME_XMPLI;
373 new_frame->name = name;
374 new_frame->name_orig_case = name;
375 new_frame->value = NULL;
376 insert_xml_frame(current_frame, new_frame);
377 new_frame->item = pi;
378 new_frame->last_item = pi;
379 new_frame->tree = pt;
380 new_frame->start_offset = tok->offset;
381 new_frame->ns = ns;
383 g_ptr_array_add(stack, new_frame);
387 static void after_xmlpi(void *tvbparse_data, const void *wanted_data _U_, tvbparse_elem_t *tok)
389 GPtrArray *stack = (GPtrArray *)tvbparse_data;
390 xml_frame_t *current_frame = (xml_frame_t *)g_ptr_array_index(stack, stack->len - 1);
392 proto_tree_add_text(current_frame->tree,
393 tok->tvb, tok->offset, tok->len, "%s",
394 tvb_format_text(tok->tvb, tok->offset, tok->len));
396 if (stack->len > 1) {
397 g_ptr_array_remove_index_fast(stack, stack->len - 1);
398 } else {
399 proto_tree_add_text(current_frame->tree, tok->tvb, tok->offset, tok->len,
400 "[ ERROR: Closing an unopened xmpli tag ]");
404 static void before_tag(void *tvbparse_data, const void *wanted_data _U_, tvbparse_elem_t *tok)
406 GPtrArray *stack = (GPtrArray *)tvbparse_data;
407 xml_frame_t *current_frame = (xml_frame_t *)g_ptr_array_index(stack, stack->len - 1);
408 tvbparse_elem_t *name_tok = tok->sub->next;
409 gchar *root_name;
410 gchar *name = NULL, *name_orig_case = NULL;
411 xml_ns_t *ns;
412 xml_frame_t *new_frame;
413 proto_item *pi;
414 proto_tree *pt;
416 if (name_tok->sub->id == XML_SCOPED_NAME) {
417 tvbparse_elem_t *root_tok = name_tok->sub->sub;
418 tvbparse_elem_t *leaf_tok = name_tok->sub->sub->next->next;
419 xml_ns_t *nameroot_ns;
421 root_name = (gchar *)tvb_get_string(wmem_packet_scope(), root_tok->tvb, root_tok->offset, root_tok->len);
422 name = (gchar *)tvb_get_string(wmem_packet_scope(), leaf_tok->tvb, leaf_tok->offset, leaf_tok->len);
423 name_orig_case = name;
425 nameroot_ns = (xml_ns_t *)g_hash_table_lookup(xml_ns.elements, root_name);
427 if(nameroot_ns) {
428 ns = (xml_ns_t *)g_hash_table_lookup(nameroot_ns->elements, name);
429 if (!ns) {
430 ns = &unknown_ns;
432 } else {
433 ns = &unknown_ns;
436 } else {
437 name = tvb_get_string(wmem_packet_scope(), name_tok->tvb, name_tok->offset, name_tok->len);
438 name_orig_case = wmem_strdup(wmem_packet_scope(), name);
439 ascii_strdown_inplace(name);
441 if(current_frame->ns) {
442 ns = (xml_ns_t *)g_hash_table_lookup(current_frame->ns->elements, name);
444 if (!ns) {
445 if (! ( ns = (xml_ns_t *)g_hash_table_lookup(root_ns->elements, name) ) ) {
446 ns = &unknown_ns;
449 } else {
450 ns = &unknown_ns;
454 pi = proto_tree_add_item(current_frame->tree, ns->hf_tag, tok->tvb, tok->offset, tok->len, ENC_UTF_8|ENC_NA);
455 proto_item_set_text(pi, "%s", tvb_format_text(tok->tvb,
456 tok->offset,
457 (name_tok->offset - tok->offset) + name_tok->len));
459 pt = proto_item_add_subtree(pi, ns->ett);
461 new_frame = (xml_frame_t *)wmem_alloc(wmem_packet_scope(), sizeof(xml_frame_t));
462 new_frame->type = XML_FRAME_TAG;
463 new_frame->name = name;
464 new_frame->name_orig_case = name_orig_case;
465 new_frame->value = NULL;
466 insert_xml_frame(current_frame, new_frame);
467 new_frame->item = pi;
468 new_frame->last_item = pi;
469 new_frame->tree = pt;
470 new_frame->start_offset = tok->offset;
471 new_frame->ns = ns;
473 g_ptr_array_add(stack, new_frame);
477 static void after_open_tag(void *tvbparse_data, const void *wanted_data _U_, tvbparse_elem_t *tok _U_)
479 GPtrArray *stack = (GPtrArray *)tvbparse_data;
480 xml_frame_t *current_frame = (xml_frame_t *)g_ptr_array_index(stack, stack->len - 1);
482 proto_item_append_text(current_frame->last_item, ">");
485 static void after_closed_tag(void *tvbparse_data, const void *wanted_data _U_, tvbparse_elem_t *tok)
487 GPtrArray *stack = (GPtrArray *)tvbparse_data;
488 xml_frame_t *current_frame = (xml_frame_t *)g_ptr_array_index(stack, stack->len - 1);
490 proto_item_append_text(current_frame->last_item, "/>");
492 if (stack->len > 1) {
493 g_ptr_array_remove_index_fast(stack, stack->len - 1);
494 } else {
495 proto_tree_add_text(current_frame->tree, tok->tvb, tok->offset, tok->len, "[ ERROR: Closing an unopened tag ]");
499 static void after_untag(void *tvbparse_data, const void *wanted_data _U_, tvbparse_elem_t *tok)
501 GPtrArray *stack = (GPtrArray *)tvbparse_data;
502 xml_frame_t *current_frame = (xml_frame_t *)g_ptr_array_index(stack, stack->len - 1);
504 proto_item_set_len(current_frame->item, (tok->offset - current_frame->start_offset) + tok->len);
506 proto_tree_add_text(current_frame->tree, tok->tvb, tok->offset, tok->len, "%s",
507 tvb_format_text(tok->tvb, tok->offset, tok->len));
509 if (stack->len > 1) {
510 g_ptr_array_remove_index_fast(stack, stack->len - 1);
511 } else {
512 proto_tree_add_text(current_frame->tree, tok->tvb, tok->offset, tok->len,
513 "[ ERROR: Closing an unopened tag ]");
517 static void before_dtd_doctype(void *tvbparse_data, const void *wanted_data _U_, tvbparse_elem_t *tok)
519 GPtrArray *stack = (GPtrArray *)tvbparse_data;
520 xml_frame_t *current_frame = (xml_frame_t *)g_ptr_array_index(stack, stack->len - 1);
521 xml_frame_t *new_frame;
522 tvbparse_elem_t *name_tok = tok->sub->next->next->next->sub->sub;
523 proto_tree *dtd_item = proto_tree_add_item(current_frame->tree, hf_doctype,
524 name_tok->tvb, name_tok->offset,
525 name_tok->len, ENC_ASCII|ENC_NA);
527 proto_item_set_text(dtd_item, "%s", tvb_format_text(tok->tvb, tok->offset, tok->len));
529 new_frame = (xml_frame_t *)wmem_alloc(wmem_packet_scope(), sizeof(xml_frame_t));
530 new_frame->type = XML_FRAME_DTD_DOCTYPE;
531 new_frame->name = (gchar *)tvb_get_string(wmem_packet_scope(), name_tok->tvb,
532 name_tok->offset,
533 name_tok->len);
534 new_frame->name_orig_case = new_frame->name;
535 new_frame->value = NULL;
536 insert_xml_frame(current_frame, new_frame);
537 new_frame->item = dtd_item;
538 new_frame->last_item = dtd_item;
539 new_frame->tree = proto_item_add_subtree(dtd_item, ett_dtd);
540 new_frame->start_offset = tok->offset;
541 new_frame->ns = NULL;
543 g_ptr_array_add(stack, new_frame);
546 static void pop_stack(void *tvbparse_data, const void *wanted_data _U_, tvbparse_elem_t *tok _U_)
548 GPtrArray *stack = (GPtrArray *)tvbparse_data;
549 xml_frame_t *current_frame = (xml_frame_t *)g_ptr_array_index(stack, stack->len - 1);
551 if (stack->len > 1) {
552 g_ptr_array_remove_index_fast(stack, stack->len - 1);
553 } else {
554 proto_tree_add_text(current_frame->tree, tok->tvb, tok->offset, tok->len,
555 "[ ERROR: Closing an unopened tag ]");
559 static void after_dtd_close(void *tvbparse_data, const void *wanted_data _U_, tvbparse_elem_t *tok)
561 GPtrArray *stack = (GPtrArray *)tvbparse_data;
562 xml_frame_t *current_frame = (xml_frame_t *)g_ptr_array_index(stack, stack->len - 1);
564 proto_tree_add_text(current_frame->tree, tok->tvb, tok->offset, tok->len, "%s",
565 tvb_format_text(tok->tvb, tok->offset, tok->len));
566 if (stack->len > 1) {
567 g_ptr_array_remove_index_fast(stack, stack->len - 1);
568 } else {
569 proto_tree_add_text(current_frame->tree, tok->tvb, tok->offset, tok->len, "[ ERROR: Closing an unopened tag ]");
573 static void get_attrib_value(void *tvbparse_data _U_, const void *wanted_data _U_, tvbparse_elem_t *tok)
575 tok->data = tok->sub;
578 static void after_attrib(void *tvbparse_data, const void *wanted_data _U_, tvbparse_elem_t *tok)
580 GPtrArray *stack = (GPtrArray *)tvbparse_data;
581 xml_frame_t *current_frame = (xml_frame_t *)g_ptr_array_index(stack, stack->len - 1);
582 gchar *name, *name_orig_case;
583 tvbparse_elem_t *value;
584 tvbparse_elem_t *value_part = (tvbparse_elem_t *)tok->sub->next->next->data;
585 int *hfidp;
586 int hfid;
587 proto_item *pi;
588 xml_frame_t *new_frame;
590 name = tvb_get_string(wmem_packet_scope(), tok->sub->tvb, tok->sub->offset, tok->sub->len);
591 name_orig_case = wmem_strdup(wmem_packet_scope(), name);
592 ascii_strdown_inplace(name);
594 if(current_frame->ns && (hfidp = (int *)g_hash_table_lookup(current_frame->ns->attributes, name) )) {
595 hfid = *hfidp;
596 value = value_part;
597 } else {
598 hfid = hf_unknowwn_attrib;
599 value = tok;
602 pi = proto_tree_add_item(current_frame->tree, hfid, value->tvb, value->offset, value->len, ENC_UTF_8|ENC_NA);
603 proto_item_set_text(pi, "%s", tvb_format_text(tok->tvb, tok->offset, tok->len));
605 current_frame->last_item = pi;
607 new_frame = (xml_frame_t *)wmem_alloc(wmem_packet_scope(), sizeof(xml_frame_t));
608 new_frame->type = XML_FRAME_ATTRIB;
609 new_frame->name = name;
610 new_frame->name_orig_case = name_orig_case;
611 new_frame->value = tvb_new_subset(value_part->tvb, value_part->offset,
612 value_part->len, value_part->len);
613 insert_xml_frame(current_frame, new_frame);
614 new_frame->item = pi;
615 new_frame->last_item = pi;
616 new_frame->tree = NULL;
617 new_frame->start_offset = tok->offset;
618 new_frame->ns = NULL;
622 static void unrecognized_token(void *tvbparse_data, const void *wanted_data _U_, tvbparse_elem_t *tok _U_)
624 GPtrArray *stack = (GPtrArray *)tvbparse_data;
625 xml_frame_t *current_frame = (xml_frame_t *)g_ptr_array_index(stack, stack->len - 1);
627 proto_tree_add_text(current_frame->tree, tok->tvb, tok->offset, tok->len, "[ ERROR: Unrecognized text ]");
633 static void init_xml_parser(void)
635 tvbparse_wanted_t *want_name =
636 tvbparse_chars(-1, 1, 0,
637 "abcdefghijklmnopqrstuvwxyz.-_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789",
638 NULL, NULL, NULL);
639 tvbparse_wanted_t *want_attr_name =
640 tvbparse_chars(-1, 1, 0,
641 "abcdefghijklmnopqrstuvwxyz.-_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789:",
642 NULL, NULL, NULL);
644 tvbparse_wanted_t *want_scoped_name = tvbparse_set_seq(XML_SCOPED_NAME, NULL, NULL, NULL,
645 want_name,
646 tvbparse_char(-1, ":", NULL, NULL, NULL),
647 want_name,
648 NULL);
650 tvbparse_wanted_t *want_tag_name = tvbparse_set_oneof(0, NULL, NULL, NULL,
651 want_scoped_name,
652 want_name,
653 NULL);
655 tvbparse_wanted_t *want_attrib_value = tvbparse_set_oneof(0, NULL, NULL, get_attrib_value,
656 tvbparse_quoted(-1, NULL, NULL, tvbparse_shrink_token_cb, '\"', '\\'),
657 tvbparse_quoted(-1, NULL, NULL, tvbparse_shrink_token_cb, '\'', '\\'),
658 tvbparse_chars(-1, 1, 0, "0123456789", NULL, NULL, NULL),
659 want_name,
660 NULL);
662 tvbparse_wanted_t *want_attributes = tvbparse_one_or_more(-1, NULL, NULL, NULL,
663 tvbparse_set_seq(-1, NULL, NULL, after_attrib,
664 want_attr_name,
665 tvbparse_char(-1, "=", NULL, NULL, NULL),
666 want_attrib_value,
667 NULL));
669 tvbparse_wanted_t *want_stoptag = tvbparse_set_oneof(-1, NULL, NULL, NULL,
670 tvbparse_char(-1, ">", NULL, NULL, after_open_tag),
671 tvbparse_string(-1, "/>", NULL, NULL, after_closed_tag),
672 NULL);
674 tvbparse_wanted_t *want_stopxmlpi = tvbparse_string(-1, "?>", NULL, NULL, after_xmlpi);
676 tvbparse_wanted_t *want_comment = tvbparse_set_seq(hf_comment, NULL, NULL, after_token,
677 tvbparse_string(-1, "<!--", NULL, NULL, NULL),
678 tvbparse_until(-1, NULL, NULL, NULL,
679 tvbparse_string(-1, "-->", NULL, NULL, NULL),
680 TP_UNTIL_INCLUDE),
681 NULL);
683 tvbparse_wanted_t *want_xmlpi = tvbparse_set_seq(hf_xmlpi, NULL, before_xmpli, NULL,
684 tvbparse_string(-1, "<?", NULL, NULL, NULL),
685 want_name,
686 tvbparse_set_oneof(-1, NULL, NULL, NULL,
687 want_stopxmlpi,
688 tvbparse_set_seq(-1, NULL, NULL, NULL,
689 want_attributes,
690 want_stopxmlpi,
691 NULL),
692 NULL),
693 NULL);
695 tvbparse_wanted_t *want_closing_tag = tvbparse_set_seq(0, NULL, NULL, after_untag,
696 tvbparse_char(-1, "<", NULL, NULL, NULL),
697 tvbparse_char(-1, "/", NULL, NULL, NULL),
698 want_tag_name,
699 tvbparse_char(-1, ">", NULL, NULL, NULL),
700 NULL);
702 tvbparse_wanted_t *want_doctype_start = tvbparse_set_seq(-1, NULL, before_dtd_doctype, NULL,
703 tvbparse_char(-1, "<", NULL, NULL, NULL),
704 tvbparse_char(-1, "!", NULL, NULL, NULL),
705 tvbparse_casestring(-1, "DOCTYPE", NULL, NULL, NULL),
706 tvbparse_set_oneof(-1, NULL, NULL, NULL,
707 tvbparse_set_seq(-1, NULL, NULL, NULL,
708 want_name,
709 tvbparse_char(-1, "[", NULL, NULL, NULL),
710 NULL),
711 tvbparse_set_seq(-1, NULL, NULL, pop_stack,
712 want_name,
713 tvbparse_set_oneof(-1, NULL, NULL, NULL,
714 tvbparse_casestring(-1, "PUBLIC", NULL, NULL, NULL),
715 tvbparse_casestring(-1, "SYSTEM", NULL, NULL, NULL),
716 NULL),
717 tvbparse_until(-1, NULL, NULL, NULL,
718 tvbparse_char(-1, ">", NULL, NULL, NULL),
719 TP_UNTIL_INCLUDE),
720 NULL),
721 NULL),
722 NULL);
724 tvbparse_wanted_t *want_dtd_tag = tvbparse_set_seq(hf_dtd_tag, NULL, NULL, after_token,
725 tvbparse_char(-1, "<", NULL, NULL, NULL),
726 tvbparse_char(-1, "!", NULL, NULL, NULL),
727 tvbparse_until(-1, NULL, NULL, NULL,
728 tvbparse_char(-1, ">", NULL, NULL, NULL),
729 TP_UNTIL_INCLUDE),
730 NULL);
732 tvbparse_wanted_t *want_tag = tvbparse_set_seq(-1, NULL, before_tag, NULL,
733 tvbparse_char(-1, "<", NULL, NULL, NULL),
734 want_tag_name,
735 tvbparse_set_oneof(-1, NULL, NULL, NULL,
736 tvbparse_set_seq(-1, NULL, NULL, NULL,
737 want_attributes,
738 want_stoptag,
739 NULL),
740 want_stoptag,
741 NULL),
742 NULL);
744 tvbparse_wanted_t *want_dtd_close = tvbparse_set_seq(-1, NULL, NULL, after_dtd_close,
745 tvbparse_char(-1, "]", NULL, NULL, NULL),
746 tvbparse_char(-1, ">", NULL, NULL, NULL),
747 NULL);
749 want_ignore = tvbparse_chars(-1, 1, 0, " \t\r\n", NULL, NULL, NULL);
752 want = tvbparse_set_oneof(-1, NULL, NULL, NULL,
753 want_comment,
754 want_xmlpi,
755 want_closing_tag,
756 want_doctype_start,
757 want_dtd_close,
758 want_dtd_tag,
759 want_tag,
760 tvbparse_not_chars(XML_CDATA, 1, 0, "<", NULL, NULL, after_token),
761 tvbparse_not_chars(-1, 1, 0, " \t\r\n", NULL, NULL, unrecognized_token),
762 NULL);
764 want_heur = tvbparse_set_oneof(-1, NULL, NULL, NULL,
765 want_comment,
766 want_xmlpi,
767 want_doctype_start,
768 want_dtd_tag,
769 want_tag,
770 NULL);
775 static xml_ns_t *xml_new_namespace(GHashTable *hash, const gchar *name, ...)
777 xml_ns_t *ns = (xml_ns_t *)g_malloc(sizeof(xml_ns_t));
778 va_list ap;
779 gchar *attr_name;
781 ns->name = g_strdup(name);
782 ns->hf_tag = -1;
783 ns->hf_cdata = -1;
784 ns->ett = -1;
785 ns->attributes = g_hash_table_new(g_str_hash, g_str_equal);
786 ns->elements = g_hash_table_new(g_str_hash, g_str_equal);
788 va_start(ap, name);
790 while(( attr_name = va_arg(ap, gchar *) )) {
791 int *hfp = (int *)g_malloc(sizeof(int));
792 *hfp = -1;
793 g_hash_table_insert(ns->attributes, g_strdup(attr_name), hfp);
796 va_end(ap);
798 g_hash_table_insert(hash, ns->name, ns);
800 return ns;
804 static void add_xml_field(wmem_array_t *hfs, int *p_id, const gchar *name, const gchar *fqn)
806 hf_register_info hfri;
808 hfri.p_id = p_id;
809 hfri.hfinfo.name = name;
810 hfri.hfinfo.abbrev = fqn;
811 hfri.hfinfo.type = FT_STRING;
812 hfri.hfinfo.display = BASE_NONE;
813 hfri.hfinfo.strings = NULL;
814 hfri.hfinfo.bitmask = 0x0;
815 hfri.hfinfo.blurb = NULL;
816 hfri.hfinfo.id = 0;
817 hfri.hfinfo.parent = 0;
818 hfri.hfinfo.ref_type = HF_REF_TYPE_NONE;
819 hfri.hfinfo.same_name_next = NULL;
820 hfri.hfinfo.same_name_prev_id = -1;
822 wmem_array_append_one(hfs, hfri);
825 static void add_xml_attribute_names(gpointer k, gpointer v, gpointer p)
827 struct _attr_reg_data *d = (struct _attr_reg_data *)p;
828 gchar *basename = wmem_strdup_printf(wmem_epan_scope(), "%s.%s", d->basename, (gchar *)k);
830 add_xml_field(d->hf, (int*) v, (gchar *)k, basename);
834 static void add_xmlpi_namespace(gpointer k _U_, gpointer v, gpointer p)
836 xml_ns_t *ns = (xml_ns_t *)v;
837 gchar *basename = wmem_strdup_printf(wmem_epan_scope(), "%s.%s", (gchar *)p, ns->name);
838 gint *ett_p = &(ns->ett);
839 struct _attr_reg_data d;
841 add_xml_field(hf_arr, &(ns->hf_tag), basename, basename);
843 g_array_append_val(ett_arr, ett_p);
845 d.basename = basename;
846 d.hf = hf_arr;
848 g_hash_table_foreach(ns->attributes, add_xml_attribute_names, &d);
852 static void destroy_dtd_data(dtd_build_data_t *dtd_data)
854 g_free(dtd_data->proto_name);
855 g_free(dtd_data->media_type);
856 g_free(dtd_data->description);
857 g_free(dtd_data->proto_root);
859 g_string_free(dtd_data->error, TRUE);
861 while(dtd_data->elements->len) {
862 dtd_named_list_t *nl = (dtd_named_list_t *)g_ptr_array_remove_index_fast(dtd_data->elements, 0);
863 g_ptr_array_free(nl->list, TRUE);
864 g_free(nl);
867 g_ptr_array_free(dtd_data->elements, TRUE);
869 while(dtd_data->attributes->len) {
870 dtd_named_list_t *nl = (dtd_named_list_t *)g_ptr_array_remove_index_fast(dtd_data->attributes, 0);
871 g_ptr_array_free(nl->list, TRUE);
872 g_free(nl);
875 g_ptr_array_free(dtd_data->attributes, TRUE);
877 g_free(dtd_data);
880 static void copy_attrib_item(gpointer k, gpointer v _U_, gpointer p)
882 gchar *key = (gchar *)g_strdup((const gchar *)k);
883 int *value = (int *)g_malloc(sizeof(int));
884 GHashTable *dst = (GHashTable *)p;
886 *value = -1;
887 g_hash_table_insert(dst, key, value);
891 static GHashTable *copy_attributes_hash(GHashTable *src)
893 GHashTable *dst = g_hash_table_new(g_str_hash, g_str_equal);
895 g_hash_table_foreach(src, copy_attrib_item, dst);
897 return dst;
900 static xml_ns_t *duplicate_element(xml_ns_t *orig)
902 xml_ns_t *new_item = (xml_ns_t *)g_malloc(sizeof(xml_ns_t));
903 guint i;
905 new_item->name = g_strdup(orig->name);
906 new_item->hf_tag = -1;
907 new_item->hf_cdata = -1;
908 new_item->ett = -1;
909 new_item->attributes = copy_attributes_hash(orig->attributes);
910 new_item->elements = g_hash_table_new(g_str_hash, g_str_equal);
911 new_item->element_names = g_ptr_array_new();
913 for(i=0; i < orig->element_names->len; i++) {
914 g_ptr_array_add(new_item->element_names,
915 g_ptr_array_index(orig->element_names, i));
918 return new_item;
921 static gchar *fully_qualified_name(GPtrArray *hier, gchar *name, gchar *proto_name)
923 guint i;
924 GString *s = g_string_new(proto_name);
925 gchar *str;
927 g_string_append(s, ".");
929 for (i = 1; i < hier->len; i++) {
930 g_string_append_printf(s, "%s.", (gchar *)g_ptr_array_index(hier, i));
933 g_string_append(s, name);
934 str = s->str;
935 g_string_free(s, FALSE);
937 return str;
941 static xml_ns_t *make_xml_hier(gchar *elem_name,
942 xml_ns_t *root,
943 GHashTable *elements,
944 GPtrArray *hier,
945 GString *error,
946 wmem_array_t *hfs,
947 GArray *etts,
948 char *proto_name)
950 xml_ns_t *fresh;
951 xml_ns_t *orig;
952 gchar *fqn;
953 gint *ett_p;
954 gboolean recurred = FALSE;
955 guint i;
956 struct _attr_reg_data d;
958 if ( g_str_equal(elem_name, root->name) ) {
959 return NULL;
962 if (! ( orig = (xml_ns_t *)g_hash_table_lookup(elements, elem_name) )) {
963 g_string_append_printf(error, "element '%s' is not defined\n", elem_name);
964 return NULL;
967 for (i = 0; i < hier->len; i++) {
968 if( strcmp(elem_name, (gchar *) g_ptr_array_index(hier, i) ) == 0 ) {
969 recurred = TRUE;
973 if (recurred) {
974 return NULL;
977 fqn = fully_qualified_name(hier, elem_name, proto_name);
979 fresh = duplicate_element(orig);
980 fresh->fqn = fqn;
982 add_xml_field(hfs, &(fresh->hf_tag), wmem_strdup(wmem_epan_scope(), elem_name), fqn);
983 add_xml_field(hfs, &(fresh->hf_cdata), wmem_strdup(wmem_epan_scope(), elem_name), fqn);
985 ett_p = &fresh->ett;
986 g_array_append_val(etts, ett_p);
988 d.basename = fqn;
989 d.hf = hfs;
991 g_hash_table_foreach(fresh->attributes, add_xml_attribute_names, &d);
993 while(fresh->element_names->len) {
994 gchar *child_name = (gchar *)g_ptr_array_remove_index(fresh->element_names, 0);
995 xml_ns_t *child_element = NULL;
997 g_ptr_array_add(hier, elem_name);
998 child_element = make_xml_hier(child_name, root, elements, hier, error, hfs, etts, proto_name);
999 g_ptr_array_remove_index_fast(hier, hier->len - 1);
1001 if (child_element) {
1002 g_hash_table_insert(fresh->elements, child_element->name, child_element);
1006 g_ptr_array_free(fresh->element_names, TRUE);
1007 fresh->element_names = NULL;
1008 return fresh;
1011 static gboolean free_both(gpointer k, gpointer v, gpointer p _U_)
1013 g_free(k);
1014 g_free(v);
1015 return TRUE;
1018 static gboolean free_elements(gpointer k _U_, gpointer v, gpointer p _U_)
1020 xml_ns_t *e = (xml_ns_t *)v;
1022 g_free(e->name);
1023 g_hash_table_foreach_remove(e->attributes, free_both, NULL);
1024 g_hash_table_destroy(e->attributes);
1025 g_hash_table_destroy(e->elements);
1027 while (e->element_names->len) {
1028 g_free(g_ptr_array_remove_index(e->element_names, 0));
1031 g_ptr_array_free(e->element_names, TRUE);
1032 g_free(e);
1034 return TRUE;
1037 static void register_dtd(dtd_build_data_t *dtd_data, GString *errors)
1039 GHashTable *elements = g_hash_table_new(g_str_hash, g_str_equal);
1040 gchar *root_name = NULL;
1041 xml_ns_t *root_element = NULL;
1042 wmem_array_t *hfs;
1043 GArray *etts;
1044 GPtrArray *hier;
1045 gchar *curr_name;
1046 GPtrArray *element_names = g_ptr_array_new();
1048 /* we first populate elements with the those coming from the parser */
1049 while(dtd_data->elements->len) {
1050 dtd_named_list_t *nl = (dtd_named_list_t *)g_ptr_array_remove_index(dtd_data->elements, 0);
1051 xml_ns_t *element = (xml_ns_t *)g_malloc(sizeof(xml_ns_t));
1053 /* we will use the first element found as root in case no other one was given. */
1054 if (root_name == NULL)
1055 root_name = g_strdup(nl->name);
1057 element->name = nl->name;
1058 element->element_names = nl->list;
1059 element->hf_tag = -1;
1060 element->hf_cdata = -1;
1061 element->ett = -1;
1062 element->attributes = g_hash_table_new(g_str_hash, g_str_equal);
1063 element->elements = g_hash_table_new(g_str_hash, g_str_equal);
1065 if( g_hash_table_lookup(elements, element->name) ) {
1066 g_string_append_printf(errors, "element %s defined more than once\n", element->name);
1067 free_elements(NULL, element, NULL);
1068 } else {
1069 g_hash_table_insert(elements, (gpointer)element->name, element);
1070 g_ptr_array_add(element_names, g_strdup(element->name));
1073 g_free(nl);
1076 /* then we add the attributes to its relative elements */
1077 while(dtd_data->attributes->len) {
1078 dtd_named_list_t *nl = (dtd_named_list_t *)g_ptr_array_remove_index(dtd_data->attributes, 0);
1079 xml_ns_t *element = (xml_ns_t *)g_hash_table_lookup(elements, nl->name);
1081 if (element) {
1082 while(nl->list->len) {
1083 gchar *name = (gchar *)g_ptr_array_remove_index(nl->list, 0);
1084 int *id_p = (int *)g_malloc(sizeof(int));
1086 *id_p = -1;
1087 g_hash_table_insert(element->attributes, name, id_p);
1090 else {
1091 g_string_append_printf(errors, "element %s is not defined\n", nl->name);
1094 g_free(nl->name);
1095 g_ptr_array_free(nl->list, TRUE);
1096 g_free(nl);
1099 /* if a proto_root is defined in the dtd we'll use that as root */
1100 if( dtd_data->proto_root ) {
1101 g_free(root_name);
1102 root_name = g_strdup(dtd_data->proto_root);
1105 /* we use a stack with the names to avoid recurring infinitelly */
1106 hier = g_ptr_array_new();
1109 * if a proto name was given in the dtd the dtd will be used as a protocol
1110 * or else the dtd will be loaded as a branch of the xml namespace
1112 if( ! dtd_data->proto_name ) {
1113 hfs = hf_arr;
1114 etts = ett_arr;
1115 g_ptr_array_add(hier, g_strdup("xml"));
1116 } else {
1118 * if we were given a proto_name the namespace will be registered
1119 * as an independent protocol with its own hf and ett arrays.
1121 hfs = wmem_array_new(wmem_epan_scope(), sizeof(hf_register_info));
1122 etts = g_array_new(FALSE, FALSE, sizeof(gint *));
1125 /* the root element of the dtd's namespace */
1126 root_element = (xml_ns_t *)g_malloc(sizeof(xml_ns_t));
1127 root_element->name = g_strdup(root_name);
1128 root_element->fqn = dtd_data->proto_name ? g_strdup(dtd_data->proto_name) : root_element->name;
1129 root_element->hf_tag = -1;
1130 root_element->hf_cdata = -1;
1131 root_element->ett = -1;
1132 root_element->elements = g_hash_table_new(g_str_hash, g_str_equal);
1133 root_element->element_names = element_names;
1136 * we can either create a namespace as a flat namespace
1137 * in which all the elements are at the root level
1138 * or we can create a recursive namespace
1140 if (dtd_data->recursion) {
1141 xml_ns_t *orig_root;
1143 make_xml_hier(root_name, root_element, elements, hier, errors, hfs, etts, dtd_data->proto_name);
1145 g_hash_table_insert(root_element->elements, (gpointer)root_element->name, root_element);
1147 orig_root = (xml_ns_t *)g_hash_table_lookup(elements, root_name);
1149 /* if the root element was defined copy its attrlist to the child */
1150 if(orig_root) {
1151 struct _attr_reg_data d;
1153 d.basename = dtd_data->proto_name;
1154 d.hf = hfs;
1156 root_element->attributes = copy_attributes_hash(orig_root->attributes);
1157 g_hash_table_foreach(root_element->attributes, add_xml_attribute_names, &d);
1158 } else {
1159 root_element->attributes = g_hash_table_new(g_str_hash, g_str_equal);
1162 /* we then create all the sub hierachies to catch the recurred cases */
1163 g_ptr_array_add(hier, root_name);
1165 while(root_element->element_names->len) {
1166 curr_name = (gchar *)g_ptr_array_remove_index(root_element->element_names, 0);
1168 if( ! g_hash_table_lookup(root_element->elements, curr_name) ) {
1169 xml_ns_t *fresh = make_xml_hier(curr_name, root_element, elements, hier, errors,
1170 hfs, etts, dtd_data->proto_name);
1171 g_hash_table_insert(root_element->elements, (gpointer)fresh->name, fresh);
1174 g_free(curr_name);
1177 } else {
1178 /* a flat namespace */
1179 g_ptr_array_add(hier, root_name);
1181 root_element->attributes = g_hash_table_new(g_str_hash, g_str_equal);
1183 while(root_element->element_names->len) {
1184 xml_ns_t *fresh;
1185 gint *ett_p;
1186 struct _attr_reg_data d;
1188 curr_name = (gchar *)g_ptr_array_remove_index(root_element->element_names, 0);
1189 fresh = duplicate_element((xml_ns_t *)g_hash_table_lookup(elements, curr_name));
1190 fresh->fqn = fully_qualified_name(hier, curr_name, root_name);
1192 add_xml_field(hfs, &(fresh->hf_tag), curr_name, fresh->fqn);
1193 add_xml_field(hfs, &(fresh->hf_cdata), curr_name, fresh->fqn);
1195 d.basename = fresh->fqn;
1196 d.hf = hfs;
1198 g_hash_table_foreach(fresh->attributes, add_xml_attribute_names, &d);
1200 ett_p = &fresh->ett;
1201 g_array_append_val(etts, ett_p);
1203 g_ptr_array_free(fresh->element_names, TRUE);
1205 g_hash_table_insert(root_element->elements, (gpointer)fresh->name, fresh);
1209 g_ptr_array_free(element_names, TRUE);
1211 g_ptr_array_free(hier, TRUE);
1214 * if we were given a proto_name the namespace will be registered
1215 * as an independent protocol.
1217 if( dtd_data->proto_name ) {
1218 gint *ett_p;
1220 if ( ! dtd_data->description) {
1221 dtd_data->description = wmem_strdup(wmem_epan_scope(), root_name);
1224 ett_p = &root_element->ett;
1225 g_array_append_val(etts, ett_p);
1227 add_xml_field(hfs, &root_element->hf_cdata, root_element->name, root_element->fqn);
1229 root_element->hf_tag = proto_register_protocol(dtd_data->description,
1230 dtd_data->proto_name,
1231 dtd_data->proto_name);
1232 proto_register_field_array(root_element->hf_tag, (hf_register_info*)wmem_array_get_raw(hfs), wmem_array_get_count(hfs));
1233 proto_register_subtree_array((gint **)g_array_data(etts), etts->len);
1235 if (dtd_data->media_type) {
1236 g_hash_table_insert(media_types, dtd_data->media_type, root_element);
1237 dtd_data->media_type = NULL;
1240 dtd_data->description = NULL;
1241 dtd_data->proto_name = NULL;
1242 g_array_free(etts, TRUE);
1245 g_hash_table_insert(xml_ns.elements, (gpointer)root_element->name, root_element);
1247 g_hash_table_foreach_remove(elements, free_elements, NULL);
1248 g_hash_table_destroy(elements);
1250 destroy_dtd_data(dtd_data);
1251 g_free(root_name);
1254 # define DIRECTORY_T GDir
1255 # define FILE_T gchar
1256 # define OPENDIR_OP(name) g_dir_open(name, 0, dummy)
1257 # define DIRGETNEXT_OP(dir) g_dir_read_name(dir)
1258 # define GETFNAME_OP(file) (file);
1259 # define CLOSEDIR_OP(dir) g_dir_close(dir)
1261 static void init_xml_names(void)
1263 xml_ns_t *xmlpi_xml_ns;
1264 guint i;
1265 DIRECTORY_T *dir;
1266 const FILE_T *file;
1267 const gchar *filename;
1268 gchar *dirname;
1270 GError **dummy = (GError **)g_malloc(sizeof(GError *));
1271 *dummy = NULL;
1273 xmpli_names = g_hash_table_new(g_str_hash, g_str_equal);
1274 media_types = g_hash_table_new(g_str_hash, g_str_equal);
1276 unknown_ns.elements = xml_ns.elements = g_hash_table_new(g_str_hash, g_str_equal);
1277 unknown_ns.attributes = xml_ns.attributes = g_hash_table_new(g_str_hash, g_str_equal);
1279 xmlpi_xml_ns = xml_new_namespace(xmpli_names, "xml", "version", "encoding", "standalone", NULL);
1281 g_hash_table_destroy(xmlpi_xml_ns->elements);
1282 xmlpi_xml_ns->elements = NULL;
1285 dirname = get_persconffile_path("dtds", FALSE);
1287 if (test_for_directory(dirname) != EISDIR) {
1288 /* Although dir isn't a directory it may still use memory */
1289 g_free(dirname);
1290 dirname = get_datafile_path("dtds");
1293 if (test_for_directory(dirname) == EISDIR) {
1294 if ((dir = OPENDIR_OP(dirname)) != NULL) {
1295 GString *errors = g_string_new("");
1297 while ((file = DIRGETNEXT_OP(dir)) != NULL) {
1298 guint namelen;
1299 filename = GETFNAME_OP(file);
1301 namelen = (int)strlen(filename);
1302 if ( namelen > 4 && ( g_ascii_strcasecmp(filename+(namelen-4), ".dtd") == 0 ) ) {
1303 GString *preparsed;
1304 dtd_build_data_t *dtd_data;
1306 g_string_truncate(errors, 0);
1307 preparsed = dtd_preparse(dirname, filename, errors);
1309 if (errors->len) {
1310 report_failure("Dtd Preparser in file %s%c%s: %s",
1311 dirname, G_DIR_SEPARATOR, filename, errors->str);
1312 continue;
1315 dtd_data = dtd_parse(preparsed);
1317 g_string_free(preparsed, TRUE);
1319 if (dtd_data->error->len) {
1320 report_failure("Dtd Parser in file %s%c%s: %s",
1321 dirname, G_DIR_SEPARATOR, filename, dtd_data->error->str);
1322 destroy_dtd_data(dtd_data);
1323 continue;
1326 register_dtd(dtd_data, errors);
1328 if (errors->len) {
1329 report_failure("Dtd Registration in file: %s%c%s: %s",
1330 dirname, G_DIR_SEPARATOR, filename, errors->str);
1331 continue;
1335 g_string_free(errors, TRUE);
1337 CLOSEDIR_OP(dir);
1341 g_free(dirname);
1343 for(i=0;i<array_length(default_media_types);i++) {
1344 if( ! g_hash_table_lookup(media_types, default_media_types[i]) ) {
1345 g_hash_table_insert(media_types, (gpointer)default_media_types[i], &xml_ns);
1349 g_hash_table_foreach(xmpli_names, add_xmlpi_namespace, (gpointer)"xml.xmlpi");
1351 g_free(dummy);
1354 static void apply_prefs(void)
1356 if (pref_heuristic_media_save != pref_heuristic_media) {
1357 if (pref_heuristic_media) {
1358 heur_dissector_add("http", dissect_xml_heur, xml_ns.hf_tag);
1359 heur_dissector_add("sip", dissect_xml_heur, xml_ns.hf_tag);
1360 heur_dissector_add("media", dissect_xml_heur, xml_ns.hf_tag);
1361 pref_heuristic_media_save = TRUE;
1362 } else {
1363 heur_dissector_delete("http", dissect_xml_heur, xml_ns.hf_tag);
1364 heur_dissector_delete("sip", dissect_xml_heur, xml_ns.hf_tag);
1365 heur_dissector_delete("media", dissect_xml_heur, xml_ns.hf_tag);
1366 pref_heuristic_media_save = FALSE;
1370 if (pref_heuristic_tcp_save != pref_heuristic_tcp ) {
1371 if (pref_heuristic_tcp) {
1372 heur_dissector_add("tcp", dissect_xml_heur, xml_ns.hf_tag);
1373 pref_heuristic_tcp_save = TRUE;
1374 } else {
1375 heur_dissector_delete("tcp", dissect_xml_heur, xml_ns.hf_tag);
1376 pref_heuristic_tcp_save = FALSE;
1380 if (pref_heuristic_udp_save != pref_heuristic_udp ) {
1381 if (pref_heuristic_udp) {
1382 heur_dissector_add("udp", dissect_xml_heur, xml_ns.hf_tag);
1383 pref_heuristic_udp_save = TRUE;
1384 } else {
1385 heur_dissector_delete("udp", dissect_xml_heur, xml_ns.hf_tag);
1386 pref_heuristic_udp_save = FALSE;
1390 dissector_delete_uint_range("tcp.port", xml_tcp_range, xml_handle);
1391 g_free(xml_tcp_range);
1392 xml_tcp_range = range_copy(global_xml_tcp_range);
1393 dissector_add_uint_range("tcp.port", xml_tcp_range, xml_handle);
1396 void
1397 proto_register_xml(void)
1399 static gint *ett_base[] = {
1400 &unknown_ns.ett,
1401 &xml_ns.ett,
1402 &ett_dtd,
1403 &ett_xmpli
1406 static hf_register_info hf_base[] = {
1407 { &hf_xmlpi,
1408 {"XMLPI", "xml.xmlpi",
1409 FT_STRING, BASE_NONE, NULL, 0,
1410 NULL, HFILL }
1412 { &hf_comment,
1413 {"Comment", "xml.comment",
1414 FT_STRING, BASE_NONE, NULL, 0,
1415 NULL, HFILL }
1417 { &hf_unknowwn_attrib,
1418 {"Attribute", "xml.attribute",
1419 FT_STRING, BASE_NONE, NULL, 0,
1420 NULL, HFILL }
1422 { &hf_doctype,
1423 {"Doctype", "xml.doctype",
1424 FT_STRING, BASE_NONE, NULL, 0,
1425 NULL, HFILL }
1427 { &hf_dtd_tag,
1428 {"DTD Tag", "xml.dtdtag",
1429 FT_STRING, BASE_NONE, NULL, 0,
1430 NULL, HFILL }
1432 { &unknown_ns.hf_cdata,
1433 {"CDATA", "xml.cdata",
1434 FT_STRING, BASE_NONE, NULL, 0, NULL,
1435 HFILL }
1437 { &unknown_ns.hf_tag,
1438 {"Tag", "xml.tag",
1439 FT_STRING, BASE_NONE, NULL, 0,
1440 NULL, HFILL }
1442 { &xml_ns.hf_cdata,
1443 {"Unknown", "xml.unknown",
1444 FT_STRING, BASE_NONE, NULL, 0,
1445 NULL, HFILL }
1448 module_t *xml_module;
1450 hf_arr = wmem_array_new(wmem_epan_scope(), sizeof(hf_register_info));
1451 ett_arr = g_array_new(FALSE, FALSE, sizeof(gint *));
1453 wmem_array_append(hf_arr, hf_base, array_length(hf_base));
1454 g_array_append_vals(ett_arr, ett_base, array_length(ett_base));
1456 init_xml_names();
1458 xml_ns.hf_tag = proto_register_protocol("eXtensible Markup Language", "XML", xml_ns.name);
1460 proto_register_field_array(xml_ns.hf_tag, (hf_register_info*)wmem_array_get_raw(hf_arr), wmem_array_get_count(hf_arr));
1461 proto_register_subtree_array((gint **)g_array_data(ett_arr), ett_arr->len);
1463 xml_module = prefs_register_protocol(xml_ns.hf_tag, apply_prefs);
1464 prefs_register_bool_preference(xml_module, "heuristic", "Use Heuristics for media types",
1465 "Try to recognize XML for unknown media types",
1466 &pref_heuristic_media);
1467 prefs_register_bool_preference(xml_module, "heuristic_tcp", "Use Heuristics for TCP",
1468 "Try to recognize XML for unknown TCP ports",
1469 &pref_heuristic_tcp);
1470 prefs_register_range_preference(xml_module, "tcp.port", "TCP Ports",
1471 "TCP Ports range",
1472 &global_xml_tcp_range, 65535);
1473 prefs_register_bool_preference(xml_module, "heuristic_udp", "Use Heuristics for UDP",
1474 "Try to recognize XML for unknown UDP ports",
1475 &pref_heuristic_udp);
1476 prefs_register_bool_preference(xml_module, "heuristic_unicode", "Use Unicode in heuristics",
1477 "Try to recognize XML encoded in Unicode (UCS-2)",
1478 &pref_heuristic_unicode);
1480 g_array_free(ett_arr, TRUE);
1482 register_dissector("xml", dissect_xml, xml_ns.hf_tag);
1484 init_xml_parser();
1486 xml_tcp_range = range_empty();
1491 static void
1492 add_dissector_media(gpointer k, gpointer v _U_, gpointer p _U_)
1494 dissector_add_string("media_type", (gchar *)k, xml_handle);
1497 void
1498 proto_reg_handoff_xml(void)
1500 xml_handle = find_dissector("xml");
1502 g_hash_table_foreach(media_types, add_dissector_media, NULL);
1503 heur_dissector_add("wtap_file", dissect_xml_heur, xml_ns.hf_tag);