2 * wireshark's xml dissector .
4 * (C) 2005, Luis E. Garcia Ontanon.
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.
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>
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
{
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
[] = {
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",
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",
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",
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
;
182 dissect_xml(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
)
185 static GPtrArray
*stack
;
186 xml_frame_t
*current_frame
;
187 const char *colinfo_str
;
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;
206 if (pinfo
->match_string
)
207 root_ns
= (xml_ns_t
*)g_hash_table_lookup(media_types
, pinfo
->match_string
);
211 colinfo_str
= "/XML";
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
);
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
);
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
;
256 if (xml_item
->type
== XML_FRAME_TAG
) {
257 if (!name
) { /* get the 1st tag */
260 } else if (xml_item
->name_orig_case
&& !strcmp(xml_item
->name_orig_case
, name
)) {
265 xml_item
= xml_item
->next_sibling
;
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
;
277 if ((xml_item
->type
== XML_FRAME_ATTRIB
) &&
278 xml_item
->name_orig_case
&& !strcmp(xml_item
->name_orig_case
, name
)) {
282 xml_item
= xml_item
->next_sibling
;
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
;
294 if (xml_item
->type
== XML_FRAME_CDATA
) {
298 xml_item
= xml_item
->next_sibling
;
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);
309 gboolean is_cdata
= FALSE
;
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
;
316 } else if ( tok
->id
> 0) {
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
));
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);
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
;
356 ascii_strdown_inplace(name
);
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
;
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);
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
;
410 gchar
*name
= NULL
, *name_orig_case
= NULL
;
412 xml_frame_t
*new_frame
;
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
);
428 ns
= (xml_ns_t
*)g_hash_table_lookup(nameroot_ns
->elements
, name
);
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
);
445 if (! ( ns
= (xml_ns_t
*)g_hash_table_lookup(root_ns
->elements
, name
) ) ) {
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
,
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
;
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);
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);
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
,
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);
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);
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
;
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
) )) {
598 hfid
= hf_unknowwn_attrib
;
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",
639 tvbparse_wanted_t
*want_attr_name
=
640 tvbparse_chars(-1, 1, 0,
641 "abcdefghijklmnopqrstuvwxyz.-_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789:",
644 tvbparse_wanted_t
*want_scoped_name
= tvbparse_set_seq(XML_SCOPED_NAME
, NULL
, NULL
, NULL
,
646 tvbparse_char(-1, ":", NULL
, NULL
, NULL
),
650 tvbparse_wanted_t
*want_tag_name
= tvbparse_set_oneof(0, NULL
, NULL
, 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
),
662 tvbparse_wanted_t
*want_attributes
= tvbparse_one_or_more(-1, NULL
, NULL
, NULL
,
663 tvbparse_set_seq(-1, NULL
, NULL
, after_attrib
,
665 tvbparse_char(-1, "=", NULL
, NULL
, 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
),
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
),
683 tvbparse_wanted_t
*want_xmlpi
= tvbparse_set_seq(hf_xmlpi
, NULL
, before_xmpli
, NULL
,
684 tvbparse_string(-1, "<?", NULL
, NULL
, NULL
),
686 tvbparse_set_oneof(-1, NULL
, NULL
, NULL
,
688 tvbparse_set_seq(-1, NULL
, NULL
, 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
),
699 tvbparse_char(-1, ">", NULL
, NULL
, 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
,
709 tvbparse_char(-1, "[", NULL
, NULL
, NULL
),
711 tvbparse_set_seq(-1, NULL
, NULL
, pop_stack
,
713 tvbparse_set_oneof(-1, NULL
, NULL
, NULL
,
714 tvbparse_casestring(-1, "PUBLIC", NULL
, NULL
, NULL
),
715 tvbparse_casestring(-1, "SYSTEM", NULL
, NULL
, NULL
),
717 tvbparse_until(-1, NULL
, NULL
, NULL
,
718 tvbparse_char(-1, ">", NULL
, NULL
, 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
),
732 tvbparse_wanted_t
*want_tag
= tvbparse_set_seq(-1, NULL
, before_tag
, NULL
,
733 tvbparse_char(-1, "<", NULL
, NULL
, NULL
),
735 tvbparse_set_oneof(-1, NULL
, NULL
, NULL
,
736 tvbparse_set_seq(-1, NULL
, NULL
, 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
),
749 want_ignore
= tvbparse_chars(-1, 1, 0, " \t\r\n", NULL
, NULL
, NULL
);
752 want
= tvbparse_set_oneof(-1, NULL
, NULL
, NULL
,
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
),
764 want_heur
= tvbparse_set_oneof(-1, NULL
, NULL
, 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
));
781 ns
->name
= g_strdup(name
);
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
);
790 while(( attr_name
= va_arg(ap
, gchar
*) )) {
791 int *hfp
= (int *)g_malloc(sizeof(int));
793 g_hash_table_insert(ns
->attributes
, g_strdup(attr_name
), hfp
);
798 g_hash_table_insert(hash
, ns
->name
, 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
;
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
;
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
;
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
);
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
);
875 g_ptr_array_free(dtd_data
->attributes
, TRUE
);
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
;
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
);
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
));
905 new_item
->name
= g_strdup(orig
->name
);
906 new_item
->hf_tag
= -1;
907 new_item
->hf_cdata
= -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
));
921 static gchar
*fully_qualified_name(GPtrArray
*hier
, gchar
*name
, gchar
*proto_name
)
924 GString
*s
= g_string_new(proto_name
);
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
);
935 g_string_free(s
, FALSE
);
941 static xml_ns_t
*make_xml_hier(gchar
*elem_name
,
943 GHashTable
*elements
,
954 gboolean recurred
= FALSE
;
956 struct _attr_reg_data d
;
958 if ( g_str_equal(elem_name
, root
->name
) ) {
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
);
967 for (i
= 0; i
< hier
->len
; i
++) {
968 if( strcmp(elem_name
, (gchar
*) g_ptr_array_index(hier
, i
) ) == 0 ) {
977 fqn
= fully_qualified_name(hier
, elem_name
, proto_name
);
979 fresh
= duplicate_element(orig
);
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
);
986 g_array_append_val(etts
, ett_p
);
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
;
1011 static gboolean
free_both(gpointer k
, gpointer v
, gpointer p _U_
)
1018 static gboolean
free_elements(gpointer k _U_
, gpointer v
, gpointer p _U_
)
1020 xml_ns_t
*e
= (xml_ns_t
*)v
;
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
);
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
;
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;
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
);
1069 g_hash_table_insert(elements
, (gpointer
)element
->name
, element
);
1070 g_ptr_array_add(element_names
, g_strdup(element
->name
));
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
);
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));
1087 g_hash_table_insert(element
->attributes
, name
, id_p
);
1091 g_string_append_printf(errors
, "element %s is not defined\n", nl
->name
);
1095 g_ptr_array_free(nl
->list
, TRUE
);
1099 /* if a proto_root is defined in the dtd we'll use that as root */
1100 if( dtd_data
->proto_root
) {
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
) {
1115 g_ptr_array_add(hier
, g_strdup("xml"));
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 */
1151 struct _attr_reg_data d
;
1153 d
.basename
= dtd_data
->proto_name
;
1156 root_element
->attributes
= copy_attributes_hash(orig_root
->attributes
);
1157 g_hash_table_foreach(root_element
->attributes
, add_xml_attribute_names
, &d
);
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
);
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
) {
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
;
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
) {
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
);
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
;
1267 const gchar
*filename
;
1270 GError
**dummy
= (GError
**)g_malloc(sizeof(GError
*));
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 */
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
) {
1299 filename
= GETFNAME_OP(file
);
1301 namelen
= (int)strlen(filename
);
1302 if ( namelen
> 4 && ( g_ascii_strcasecmp(filename
+(namelen
-4), ".dtd") == 0 ) ) {
1304 dtd_build_data_t
*dtd_data
;
1306 g_string_truncate(errors
, 0);
1307 preparsed
= dtd_preparse(dirname
, filename
, errors
);
1310 report_failure("Dtd Preparser in file %s%c%s: %s",
1311 dirname
, G_DIR_SEPARATOR
, filename
, errors
->str
);
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
);
1326 register_dtd(dtd_data
, errors
);
1329 report_failure("Dtd Registration in file: %s%c%s: %s",
1330 dirname
, G_DIR_SEPARATOR
, filename
, errors
->str
);
1335 g_string_free(errors
, TRUE
);
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");
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
;
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
;
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
;
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
);
1397 proto_register_xml(void)
1399 static gint
*ett_base
[] = {
1406 static hf_register_info hf_base
[] = {
1408 {"XMLPI", "xml.xmlpi",
1409 FT_STRING
, BASE_NONE
, NULL
, 0,
1413 {"Comment", "xml.comment",
1414 FT_STRING
, BASE_NONE
, NULL
, 0,
1417 { &hf_unknowwn_attrib
,
1418 {"Attribute", "xml.attribute",
1419 FT_STRING
, BASE_NONE
, NULL
, 0,
1423 {"Doctype", "xml.doctype",
1424 FT_STRING
, BASE_NONE
, NULL
, 0,
1428 {"DTD Tag", "xml.dtdtag",
1429 FT_STRING
, BASE_NONE
, NULL
, 0,
1432 { &unknown_ns
.hf_cdata
,
1433 {"CDATA", "xml.cdata",
1434 FT_STRING
, BASE_NONE
, NULL
, 0, NULL
,
1437 { &unknown_ns
.hf_tag
,
1439 FT_STRING
, BASE_NONE
, NULL
, 0,
1443 {"Unknown", "xml.unknown",
1444 FT_STRING
, BASE_NONE
, NULL
, 0,
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
));
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",
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
);
1486 xml_tcp_range
= range_empty();
1492 add_dissector_media(gpointer k
, gpointer v _U_
, gpointer p _U_
)
1494 dissector_add_string("media_type", (gchar
*)k
, xml_handle
);
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
);