diff options
author | Luis Ontanon <luis.ontanon@gmail.com> | 2005-09-17 17:05:46 +0000 |
---|---|---|
committer | Luis Ontanon <luis.ontanon@gmail.com> | 2005-09-17 17:05:46 +0000 |
commit | 4c14b12c25291919fc7e409f9cfe95c16cefe678 (patch) | |
tree | 432eb53c8e154b0e76f997c778b30c476637985c /epan/dissectors/packet-xml.c | |
parent | 8ace2749f38daec92df4da8cf2d1eda298cf36ff (diff) |
Because there's more than just text in XML...
DTDs are imported to create fields
svn path=/trunk/; revision=15851
Diffstat (limited to 'epan/dissectors/packet-xml.c')
-rw-r--r-- | epan/dissectors/packet-xml.c | 696 |
1 files changed, 589 insertions, 107 deletions
diff --git a/epan/dissectors/packet-xml.c b/epan/dissectors/packet-xml.c index 5c3ac3238a..e98598198c 100644 --- a/epan/dissectors/packet-xml.c +++ b/epan/dissectors/packet-xml.c @@ -31,10 +31,15 @@ #include "config.h" #endif +#ifdef HAVE_DIRENT_H +#include <dirent.h> +#endif + #include <ctype.h> #include <stdlib.h> #include <string.h> #include <stdarg.h> +#include <errno.h> #include <stdio.h> @@ -44,58 +49,109 @@ #include <epan/strutil.h> #include <epan/tvbparse.h> #include <epan/dtd.h> +#include <epan/report_err.h> +#include <epan/filesystem.h> -typedef struct _xml_names_t { +typedef struct _xml_ns_t { + /* the name of this namespace */ gchar* name; - gchar* longname; - gchar* blurb; + + /* its fully qualified name */ + gchar* fqn; + + /* the contents of the whole element from <> to </> */ int hf_tag; + + /* chunks of cdata from <> to </> excluding sub tags */ int hf_cdata; + + /* the subtree for its sub items */ gint ett; - - gboolean is_root; GHashTable* attributes; - GHashTable* elements; -} xml_names_t; + /* key: the attribute name + value: hf_id of what's between quotes */ + + /* the namespace's namespaces */ + GHashTable* elements; + /* key: the element name + value: the child namespace */ + + GPtrArray* element_names; + /* imported directly from the parser and used while building the namespace */ + +} xml_ns_t; typedef struct { proto_tree* tree; proto_item* item; proto_item* last_item; - xml_names_t* ns; + xml_ns_t* ns; int start_offset; } xml_frame_t; +struct _attr_reg_data { + GArray* hf; + gchar* basename; +}; + + static gint ett_dtd = -1; static gint ett_xmpli = -1; -static int hf_junk = -1; static int hf_unknowwn_attrib = -1; static int hf_comment = -1; static int hf_xmlpi = -1; static int hf_dtd_tag = -1; static int hf_doctype = -1; -/* Dissector handles */ +/* dissector handles */ static dissector_handle_t xml_handle; -/* tokenizer defs */ +/* parser definitions */ static tvbparse_wanted_t* want; static tvbparse_wanted_t* want_ignore; static GHashTable* xmpli_names; static GHashTable* media_types; -static xml_names_t xml_ns = {"xml","eXtesible Markup Language","XML",-1,-1,-1,TRUE,NULL,NULL}; -static xml_names_t unknown_ns = {"","","",-1,-1,-1,TRUE,NULL,NULL}; -static xml_names_t* root_ns; +static xml_ns_t xml_ns = {"xml","/",-1,-1,-1,NULL,NULL,NULL}; +static xml_ns_t unknown_ns = {"unknown","?",-1,-1,-1,NULL,NULL,NULL}; +static xml_ns_t* root_ns; #define XML_CDATA -1000 +#define XML_SCOPED_NAME -1001 -GArray* hf; + +GArray* hf_arr; GArray* ett_arr; +static const gchar* default_media_types[] = { + "text/xml", + "application/xml", + "application/soap+xml", + "application/xml-dtd", + "text/vnd.wap.wml", + "text/vnd.wap.si", + "text/vnd.wap.sl", + "text/vnd.wap.co", + "text/vnd.wap.emn", + "application/vnd.wv.csp+xml", + "application/xcap-el+xml", + "application/xcap-att+xml", + "application/xcap-error+xml", + "application/xcap-caps+xml", + "application/auth-policy+xml", + "application/smil", + "application/cpim-pidf+xml", + "application/rdf+xml", + "application/xslt+xml", + "application/mathml+xml", + "image/svg+xml", + "application/vnd.wv.csp.xml", +}; + + static void dissect_xml(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { @@ -119,13 +175,13 @@ dissect_xml(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) root_ns = g_hash_table_lookup(media_types,pinfo->match_string); if (! root_ns ) { - root_ns = &unknown_ns; + root_ns = &xml_ns; } current_frame->ns = root_ns; - current_frame->item = proto_tree_add_item(tree,xml_ns.hf_tag,tvb,0,-1,FALSE); - current_frame->tree = proto_item_add_subtree(current_frame->item,xml_ns.ett); + current_frame->item = proto_tree_add_item(tree,current_frame->ns->hf_tag,tvb,0,-1,FALSE); + current_frame->tree = proto_item_add_subtree(current_frame->item,current_frame->ns->ett); current_frame->last_item = current_frame->item; while(( tok = tvbparse_get(tt, want) )) ; @@ -143,7 +199,7 @@ static void after_token(void* tvbparse_data, const void* wanted_data _U_, tvbpar } else if ( tok->id > 0) { hfid = tok->id; } else { - hfid = hf_junk; + hfid = xml_ns.hf_cdata; } pi = proto_tree_add_item(current_frame->tree, hfid, tok->tvb, tok->offset, tok->len, FALSE); @@ -159,7 +215,8 @@ static void before_xmpli(void* tvbparse_data, const void* wanted_data _U_, tvbpa proto_tree* pt; tvbparse_elem_t* name_tok = tok->sub->next; gchar* name = tvb_get_ephemeral_string(name_tok->tvb,name_tok->offset,name_tok->len); - xml_names_t* ns = g_hash_table_lookup(xmpli_names,name); + xml_ns_t* ns = g_hash_table_lookup(xmpli_names,name); + int hf_tag; gint ett; @@ -208,20 +265,46 @@ static void before_tag(void* tvbparse_data, const void* wanted_data _U_, tvbpars GPtrArray* stack = tvbparse_data; xml_frame_t* current_frame = g_ptr_array_index(stack,stack->len - 1); tvbparse_elem_t* name_tok = tok->sub->next; - gchar* name =tvb_get_ephemeral_string(name_tok->tvb,name_tok->offset,name_tok->len); - xml_names_t* ns = g_hash_table_lookup(current_frame->ns->elements,name); + gchar* root_name; + gchar* name; + xml_ns_t* ns; xml_frame_t* new_frame; proto_item* pi; proto_tree* pt; - - g_strdown(name); - if (!ns) { - if (! ( ns = g_hash_table_lookup(root_ns->elements,name) ) ) { - ns = &unknown_ns; - } - } - - pi = proto_tree_add_item(current_frame->tree,ns->hf_tag,tok->tvb,tok->offset,tok->len,FALSE); + + if (name_tok->sub->id == XML_SCOPED_NAME) { + tvbparse_elem_t* root_tok = name_tok->sub->sub; + tvbparse_elem_t* leaf_tok = name_tok->sub->sub->next->next; + xml_ns_t* nameroot_ns; + + root_name = tvb_get_ephemeral_string(root_tok->tvb,root_tok->offset,root_tok->len); + name = tvb_get_ephemeral_string(leaf_tok->tvb,leaf_tok->offset,leaf_tok->len); + + nameroot_ns = g_hash_table_lookup(xml_ns.elements,root_name); + + if(nameroot_ns) { + ns = g_hash_table_lookup(nameroot_ns->elements,name); + if (!ns) { + ns = &unknown_ns; + } + } else { + ns = &unknown_ns; + } + + } else { + name = tvb_get_ephemeral_string(name_tok->tvb,name_tok->offset,name_tok->len); + g_strdown(name); + + ns = g_hash_table_lookup(current_frame->ns->elements,name); + + if (!ns) { + if (! ( ns = g_hash_table_lookup(root_ns->elements,name) ) ) { + ns = &unknown_ns; + } + } + } + + pi = proto_tree_add_item(current_frame->tree,ns->hf_tag,tok->tvb,tok->offset,tok->len,FALSE); proto_item_set_text(pi,tvb_format_text(tok->tvb,tok->offset,(name_tok->offset - tok->offset) + name_tok->len)); pt = proto_item_add_subtree(pi,ns->ett); @@ -354,11 +437,20 @@ static void unrecognized_token(void* tvbparse_data, const void* wanted_data _U_, void init_xml_parser(void) { - tvbparse_wanted_t* want_name = tvbparse_chars(-1,0,0,"abcdefghijklmnopqrstuvwxyz-_:ABCDEFGHIJKLMNOPQRSTUVWXYZ",NULL,NULL,NULL); - + tvbparse_wanted_t* want_name = tvbparse_chars(-1,0,0,"abcdefghijklmnopqrstuvwxyz-_ABCDEFGHIJKLMNOPQRSTUVWXYZ",NULL,NULL,NULL); + + tvbparse_wanted_t* want_tag_name = tvbparse_set_oneof(0, NULL, NULL, NULL, + tvbparse_set_seq(XML_SCOPED_NAME, NULL, NULL, NULL, + want_name, + tvbparse_char(-1,":",NULL,NULL,NULL), + want_name, + NULL), + want_name, + NULL); + tvbparse_wanted_t* want_attributes = tvbparse_one_or_more(-1, NULL, NULL, NULL, tvbparse_set_seq(-1, NULL, NULL, after_attrib, - want_name, + tvbparse_chars(-1,0,0,"abcdefghijklmnopqrstuvwxyz-_ABCDEFGHIJKLMNOPQRSTUVWXYZ:",NULL,NULL,NULL), tvbparse_char(-1,"=",NULL,NULL,NULL), tvbparse_set_oneof(0, NULL, NULL, get_attrib_value, tvbparse_quoted(-1, NULL, NULL, tvbparse_shrink_token_cb,'\"','\\'), @@ -398,7 +490,7 @@ void init_xml_parser(void) { tvbparse_set_seq(0,NULL,NULL,after_untag, tvbparse_char(-1, "<", NULL, NULL, NULL), tvbparse_char(-1, "/", NULL, NULL, NULL), - want_name, + want_tag_name, tvbparse_char(-1, ">", NULL, NULL, NULL), NULL), tvbparse_set_seq(-1,NULL,before_dtd_doctype,NULL, @@ -435,7 +527,7 @@ void init_xml_parser(void) { NULL), tvbparse_set_seq(-1, NULL, before_tag, NULL, tvbparse_char(-1,"<",NULL,NULL,NULL), - want_name, + want_tag_name, tvbparse_set_oneof(-1,NULL,NULL,NULL, tvbparse_set_seq(-1,NULL,NULL,NULL, want_attributes, @@ -452,21 +544,19 @@ void init_xml_parser(void) { } -xml_names_t* xml_new_namespace(GHashTable* hash, gchar* name, gchar* longname, gchar* blurb, ...) { - xml_names_t* ns = g_malloc(sizeof(xml_names_t)); +xml_ns_t* xml_new_namespace(GHashTable* hash, gchar* name, ...) { + xml_ns_t* ns = g_malloc(sizeof(xml_ns_t)); va_list ap; gchar* attr_name; ns->name = g_strdup(name); - ns->longname = g_strdup(longname); - ns->blurb = g_strdup(blurb); ns->hf_tag = -1; ns->hf_cdata = -1; ns->ett = -1; ns->attributes = g_hash_table_new(g_str_hash,g_str_equal); ns->elements = g_hash_table_new(g_str_hash,g_str_equal); - va_start(ap,blurb); + va_start(ap,name); while(( attr_name = va_arg(ap,gchar*) )) { int* hfp = g_malloc(sizeof(int)); @@ -481,18 +571,18 @@ xml_names_t* xml_new_namespace(GHashTable* hash, gchar* name, gchar* longname, g return ns; } -void add_xml_attribute_names(gpointer k, gpointer v, gpointer p) { - gchar* basename = g_strdup_printf("%s.%s",(gchar*)p,(gchar*)k); + +void add_xml_field(GArray* hfs, int* p_id, gchar* name, gchar* fqn) { hf_register_info hfri; - hfri.p_id = (int*)v; - hfri.hfinfo.name = basename; - hfri.hfinfo.abbrev = basename; + hfri.p_id = p_id; + hfri.hfinfo.name = name; + hfri.hfinfo.abbrev = fqn; hfri.hfinfo.type = FT_STRING; hfri.hfinfo.display = BASE_NONE; hfri.hfinfo.strings = NULL; hfri.hfinfo.bitmask = 0x0; - hfri.hfinfo.blurb = basename; + hfri.hfinfo.blurb = ""; hfri.hfinfo.id = 0; hfri.hfinfo.parent = 0; hfri.hfinfo.ref_count = 0; @@ -500,55 +590,469 @@ void add_xml_attribute_names(gpointer k, gpointer v, gpointer p) { hfri.hfinfo.same_name_next = NULL; hfri.hfinfo.same_name_prev = NULL; - g_array_append_val(hf,hfri); + g_array_append_val(hfs,hfri); +} + +void add_xml_attribute_names(gpointer k, gpointer v, gpointer p) { + struct _attr_reg_data* d = p; + gchar* basename = g_strdup_printf("%s.%s",d->basename,(gchar*)k); + add_xml_field(d->hf, (int*) v, (gchar*)k, basename); } + void add_xmlpi_namespace(gpointer k _U_, gpointer v, gpointer p) { - xml_names_t* ns = v; - hf_register_info hfri; + xml_ns_t* ns = v; gchar* basename = g_strdup_printf("%s.%s",(gchar*)p,ns->name); gint* ett_p = &(ns->ett); - - hfri.p_id = &(ns->hf_tag); - hfri.hfinfo.name = basename; - hfri.hfinfo.abbrev = basename; - hfri.hfinfo.type = FT_STRING; - hfri.hfinfo.display = BASE_NONE; - hfri.hfinfo.strings = NULL; - hfri.hfinfo.bitmask = 0x0; - hfri.hfinfo.blurb = basename; - hfri.hfinfo.id = 0; - hfri.hfinfo.parent = 0; - hfri.hfinfo.ref_count = 0; - hfri.hfinfo.bitshift = 0; - hfri.hfinfo.same_name_next = NULL; - hfri.hfinfo.same_name_prev = NULL; + struct _attr_reg_data d; + + add_xml_field(hf_arr, &(ns->hf_tag), basename, basename); - g_array_append_val(hf,hfri); g_array_append_val(ett_arr,ett_p); - g_hash_table_foreach(ns->attributes,add_xml_attribute_names,basename); + d.basename = basename; + d.hf = hf_arr; + + g_hash_table_foreach(ns->attributes,add_xml_attribute_names,&d); } -void init_xml_names(void) { - xml_names_t* xmlpi_xml_ns; +static void destroy_dtd_data(dtd_build_data_t* dtd_data) { + if(dtd_data->proto_name) g_free(dtd_data->proto_name); + if(dtd_data->media_type) g_free(dtd_data->media_type); + if(dtd_data->description) g_free(dtd_data->description); + if(dtd_data->proto_root) g_free(dtd_data->proto_root); + + if(dtd_data->location) g_free(dtd_data->location); + g_string_free(dtd_data->error,TRUE); + + + while(dtd_data->elements->len) { + dtd_named_list_t* nl = g_ptr_array_remove_index_fast(dtd_data->elements,0); + g_ptr_array_free(nl->list,TRUE); + g_free(nl); + } + + g_ptr_array_free(dtd_data->elements,FALSE); + + while(dtd_data->attributes->len) { + dtd_named_list_t* nl = g_ptr_array_remove_index_fast(dtd_data->elements,0); + g_ptr_array_free(nl->list,TRUE); + g_free(nl); + } + + g_ptr_array_free(dtd_data->attributes,FALSE); + + g_free(dtd_data); + +} + + +static void copy_attrib_item(gpointer k, gpointer v _U_, gpointer p) { + gchar* key = g_strdup(k); + int* value = g_malloc(sizeof(int)); + GHashTable* dst = p; + + *value = -1; + g_hash_table_insert(dst,key,value); + +} + +static GHashTable* copy_attributes_hash(GHashTable* src) { + GHashTable* dst = g_hash_table_new(g_str_hash,g_str_equal); + + g_hash_table_foreach(src,copy_attrib_item,dst); + + return dst; +} + +static xml_ns_t* duplicate_element(xml_ns_t* orig) { + xml_ns_t* new_item = g_malloc(sizeof(xml_ns_t)); + guint i; + + new_item->name = g_strdup(orig->name); + new_item->hf_tag = -1; + new_item->hf_cdata = -1; + new_item->ett = -1; + new_item->attributes = copy_attributes_hash(orig->attributes); + new_item->elements = g_hash_table_new(g_str_hash,g_str_equal); + new_item->element_names = g_ptr_array_new(); + + for(i=0; i < orig->element_names->len; i++) { + g_ptr_array_add(new_item->element_names, + g_ptr_array_index(orig->element_names,i)); + } + + return new_item; +} + +static gchar* fully_qualified_name(GPtrArray* hier, gchar* name) { + guint i; + GString* s = g_string_new(""); + gchar* str; + + for (i = 0; i < hier->len; i++) { + g_string_sprintfa(s, "%s.",(gchar*)g_ptr_array_index(hier,i)); + } + + g_string_append(s,name); + str = s->str; + g_string_free(s,FALSE); + + return str; +} + + +static xml_ns_t* make_xml_hier(gchar* elem_name, + xml_ns_t* root, + GHashTable* elements, + GPtrArray* hier, + GString* error, + GArray* hfs, + GArray* etts) { + xml_ns_t* new; + xml_ns_t* orig = g_hash_table_lookup(elements,elem_name); + gchar* fqn; + gint* ett_p; + struct _attr_reg_data d; + gboolean recurred = FALSE; + + if ( g_str_equal(elem_name,root->name) ) { + return NULL; + } + + if (! orig) { + g_string_sprintfa(error,"element '%s' is not defined\n", elem_name); + return NULL; + } + + fqn = fully_qualified_name(hier,elem_name); + + new = duplicate_element(orig); + new->fqn = fqn; + + add_xml_field(hfs, &(new->hf_tag), elem_name, fqn); + add_xml_field(hfs, &(new->hf_cdata), elem_name, fqn); + + ett_p = &new->ett; + g_array_append_val(etts,ett_p); + + d.basename = fqn; + d.hf = hfs; + + g_hash_table_foreach(new->attributes,add_xml_attribute_names,&d); + + while(new->element_names->len) { + gchar* child_name = g_ptr_array_remove_index(new->element_names,0); + xml_ns_t* child_element = NULL; + guint i; + + for (i = 0; i < hier->len; i++) { + if( strcmp(child_name,(gchar*) g_ptr_array_index(hier,i) ) == 0 ) { + recurred = TRUE; + } + } + + if( ! recurred ) { + g_ptr_array_add(hier,elem_name); + child_element = make_xml_hier(child_name, root, elements, hier,error,hfs,etts); + g_ptr_array_remove_index_fast(hier,hier->len - 1); + } + + if (child_element) { + g_hash_table_insert(new->elements,child_element->name,child_element); + } + } + + g_ptr_array_free(new->element_names,FALSE); + new->element_names = NULL; + return new; +} + +static void register_dtd(dtd_build_data_t* dtd_data, GString* errors) { + GHashTable* elements = g_hash_table_new(g_str_hash,g_str_equal); + gchar* root_name = NULL; + xml_ns_t* root_element = NULL; + GArray* hfs; + GArray* etts; + GPtrArray* hier; + gchar* curr_name; + GPtrArray* element_names = g_ptr_array_new(); + + /* we first populate elements with the those coming from the parser */ + while(dtd_data->elements->len) { + dtd_named_list_t* nl = g_ptr_array_remove_index(dtd_data->elements,0); + xml_ns_t* element = g_malloc(sizeof(xml_ns_t)); + + /* we will use the first element found as root in case no other one was given. */ + if (root_name == NULL) root_name = g_strdup(nl->name); + + element->name = nl->name; + element->element_names = nl->list; + element->hf_tag = -1; + element->hf_cdata = -1; + element->ett = -1; + element->attributes = g_hash_table_new(g_str_hash,g_str_equal); + element->elements = g_hash_table_new(g_str_hash,g_str_equal); + + g_hash_table_insert(elements,element->name,element); + g_ptr_array_add(element_names,element->name); + + g_free(nl); + } + + /* then we add the attributes to its relative elements */ + while(dtd_data->attributes->len) { + dtd_named_list_t* nl = g_ptr_array_remove_index(dtd_data->attributes,0); + xml_ns_t* element = g_hash_table_lookup(elements,nl->name); + + if (!element) { + g_string_sprintfa(errors,"no element %s is been defined\n", nl->name); + + goto next_attribute; + } + + while(nl->list->len) { + gchar* name = g_ptr_array_remove_index(nl->list,0); + int* id_p = g_malloc(sizeof(int)); + + *id_p = -1; + g_hash_table_insert(element->attributes,name,id_p); + } + +next_attribute: + g_free(nl->name); + g_ptr_array_free(nl->list,FALSE); + g_free(nl); + } + + + + if( dtd_data->proto_root ) { + if(root_name) g_free(root_name); + root_name = g_strdup(dtd_data->proto_root); + } + + hier = g_ptr_array_new(); + + if( ! dtd_data->proto_name ) { + hfs = hf_arr; + etts = ett_arr; + g_ptr_array_add(hier,g_strdup("xml")); + root_element = &xml_ns; + } else { + hfs = g_array_new(FALSE,FALSE,sizeof(hf_register_info)); + etts = g_array_new(FALSE,FALSE,sizeof(gint*)); + } + + root_element = g_malloc(sizeof(xml_ns_t)); + root_element->name = g_strdup(root_name); + root_element->fqn = root_element->name; + root_element->hf_tag = -1; + root_element->hf_cdata = -1; + root_element->ett = -1; + root_element->elements = g_hash_table_new(g_str_hash,g_str_equal); + root_element->element_names = element_names; + + if (dtd_data->recursion) { + xml_ns_t* orig_root; + + make_xml_hier(root_name, root_element, elements,hier,errors,hfs,etts); + + g_hash_table_insert(root_element->elements,root_element->name,root_element); + + orig_root = g_hash_table_lookup(elements,root_name); + + if(orig_root) { + struct _attr_reg_data d; + + d.basename = root_name; + d.hf = hfs; + + root_element->attributes = copy_attributes_hash(orig_root->attributes); + g_hash_table_foreach(root_element->attributes,add_xml_attribute_names,&d); + } else { + root_element->attributes = g_hash_table_new(g_str_hash,g_str_equal); + } + + g_ptr_array_add(hier,root_name); + + while(root_element->element_names->len) { + curr_name = g_ptr_array_remove_index(root_element->element_names,0); + + if( ! g_hash_table_lookup(root_element->elements,curr_name) ) { + xml_ns_t* new = make_xml_hier(curr_name, root_element, elements,hier,errors,hfs,etts); + g_hash_table_insert(root_element->elements,new->name,new); + } + } + } else { + g_ptr_array_add(hier,root_name); + + root_element->attributes = g_hash_table_new(g_str_hash,g_str_equal); + + while(root_element->element_names->len) { + xml_ns_t* new; + gint* ett_p; + struct _attr_reg_data d; + + curr_name = g_ptr_array_remove_index(root_element->element_names,0); + new = duplicate_element(g_hash_table_lookup(elements,curr_name)); + new->fqn = fully_qualified_name(hier, curr_name); + + add_xml_field(hfs, &(new->hf_tag), curr_name, new->fqn); + add_xml_field(hfs, &(new->hf_cdata), curr_name, new->fqn); + + d.basename = new->fqn; + d.hf = hfs; + + g_hash_table_foreach(new->attributes,add_xml_attribute_names,&d); + + ett_p = &new->ett; + g_array_append_val(etts,ett_p); + + g_hash_table_insert(root_element->elements,new->name,new); + + } + } + + g_ptr_array_free(element_names,FALSE); + + g_ptr_array_free(hier,FALSE); + + if( dtd_data->proto_name ) { + gint* ett_p; + + if ( ! dtd_data->description) { + dtd_data->description = g_strdup(root_name); + } + + ett_p = &root_element->ett; + g_array_append_val(etts,ett_p); + + add_xml_field(hfs, &root_element->hf_cdata, root_element->name, root_element->fqn); + + root_element->hf_tag = proto_register_protocol(dtd_data->description, dtd_data->proto_name, root_element->name); + proto_register_field_array(root_element->hf_tag, (hf_register_info*)hfs->data, hfs->len); + proto_register_subtree_array((gint**)etts->data, etts->len); + + if (dtd_data->media_type) { + g_hash_table_insert(media_types,dtd_data->media_type,root_element); + dtd_data->media_type = NULL; + } + + dtd_data->description = NULL; + dtd_data->proto_name = NULL; + g_array_free(hfs,FALSE); + g_array_free(etts,FALSE); + } + + g_hash_table_insert(xml_ns.elements,root_element->name,root_element); + + destroy_dtd_data(dtd_data); +} + +#if GLIB_MAJOR_VERSION < 2 +# define DIRECTORY_T DIR +# define FILE_T struct dirent +# define OPENDIR_OP(name) opendir(name) +# define DIRGETNEXT_OP(dir) readdir(dir) +# define GETFNAME_OP(file) (gchar *)file->d_name +# define CLOSEDIR_OP(dir) closedir(dir) +#else /* GLIB 2 */ +# define DIRECTORY_T GDir +# define FILE_T gchar +# define OPENDIR_OP(name) g_dir_open(name, 0, dummy) +# define DIRGETNEXT_OP(dir) g_dir_read_name(dir) +# define GETFNAME_OP(file) (file); +# define CLOSEDIR_OP(dir) g_dir_close(dir) +#endif + +void init_xml_names(void) { + xml_ns_t* xmlpi_xml_ns; + guint i; + DIRECTORY_T* dir; + const FILE_T* file; + const gchar* filename; + gchar* dirname; + +#if GLIB_MAJOR_VERSION >= 2 + GError** dummy = g_malloc(sizeof(GError *)); + *dummy = NULL; +#endif + xmpli_names = g_hash_table_new(g_str_hash,g_str_equal); media_types = g_hash_table_new(g_str_hash,g_str_equal); - unknown_ns.elements = g_hash_table_new(g_str_hash,g_str_equal); - unknown_ns.attributes = g_hash_table_new(g_str_hash,g_str_equal); + unknown_ns.elements = xml_ns.elements = g_hash_table_new(g_str_hash,g_str_equal); + unknown_ns.attributes = xml_ns.attributes = g_hash_table_new(g_str_hash,g_str_equal); - xmlpi_xml_ns = xml_new_namespace(xmpli_names,"xml","XML XMLPI","XML XMLPI", - "version","encoding","standalone",NULL); + xmlpi_xml_ns = xml_new_namespace(xmpli_names,"xml","version","encoding","standalone",NULL); g_hash_table_destroy(xmlpi_xml_ns->elements); xmlpi_xml_ns->elements = NULL; + + + dirname = get_persconffile_path("dtds", FALSE); + + if (test_for_directory(dirname) != EISDIR) { + dirname = get_datafile_path("dtds"); + } + + if (test_for_directory(dirname) == EISDIR) { + + if ((dir = OPENDIR_OP(dirname)) != NULL) { + while ((file = DIRGETNEXT_OP(dir)) != NULL) { + guint namelen; + filename = GETFNAME_OP(file); + + namelen = strlen(filename); + if ( namelen > 4 && ( g_strcasecmp(filename+(namelen-4),".dtd") == 0 ) ) { + GString* errors = g_string_new(""); + GString* preparsed = dtd_preparse(dirname, filename, errors); + dtd_build_data_t* dtd_data; + + if (errors->len) { + report_failure("Dtd Preparser in file %s%c%s: %s",dirname,G_DIR_SEPARATOR,filename,errors->str); + continue; + } + + dtd_data = dtd_parse(preparsed); + + g_string_free(preparsed,TRUE); + + if (dtd_data->error->len) { + report_failure("Dtd Parser in file %s%c%s: %s",dirname,G_DIR_SEPARATOR,filename,dtd_data->error->str); + destroy_dtd_data(dtd_data); + continue; + } + + register_dtd(dtd_data,errors); + + if (errors->len) { + report_failure("Dtd Registration in file: %s%c%s: %s",dirname,G_DIR_SEPARATOR,filename,errors->str); + g_string_free(errors,TRUE); + continue; + } + } + } + + CLOSEDIR_OP(dir); + } + } + + for(i=0;i<array_length(default_media_types);i++) { + if( ! g_hash_table_lookup(media_types,default_media_types[i]) ) { + g_hash_table_insert(media_types,(gpointer)default_media_types[i],&xml_ns); + } + } g_hash_table_foreach(xmpli_names,add_xmlpi_namespace,"xml.xmlpi"); -} +#if GLIB_MAJOR_VERSION >= 2 + g_free(dummy); +#endif +} void proto_register_xml(void) { @@ -568,25 +1072,30 @@ proto_register_xml(void) { { &hf_dtd_tag, {"DTD Tag", "xml.dtdtag", FT_STRING, BASE_NONE, NULL, 0, "", HFILL }}, { &unknown_ns.hf_cdata, {"CDATA", "xml.cdata", FT_STRING, BASE_NONE, NULL, 0, "", HFILL }}, { &unknown_ns.hf_tag, {"Tag", "xml.tag", FT_STRING, BASE_NONE, NULL, 0, "", HFILL }}, - { &hf_junk, {"Unknown", "xml.unknown", FT_STRING, BASE_NONE, NULL, 0, "", HFILL }} + { &xml_ns.hf_cdata, {"Unknown", "xml.unknown", FT_STRING, BASE_NONE, NULL, 0, "", HFILL }} }; - hf = g_array_new(FALSE,FALSE,sizeof(hf_register_info)); + hf_arr = g_array_new(FALSE,FALSE,sizeof(hf_register_info)); ett_arr = g_array_new(FALSE,FALSE,sizeof(gint*)); - g_array_append_vals(hf,hf_base,array_length(hf_base)); + g_array_append_vals(hf_arr,hf_base,array_length(hf_base)); g_array_append_vals(ett_arr,ett_base,array_length(ett_base)); init_xml_names(); - xml_ns.hf_tag = proto_register_protocol(xml_ns.blurb, xml_ns.longname, xml_ns.name); + xml_ns.hf_tag = proto_register_protocol("eXtensible Markup Language", "XML", xml_ns.name); - proto_register_field_array(xml_ns.hf_tag, (hf_register_info*)hf->data, hf->len); + proto_register_field_array(xml_ns.hf_tag, (hf_register_info*)hf_arr->data, hf_arr->len); proto_register_subtree_array((gint**)ett_arr->data, ett_arr->len); register_dissector("xml", dissect_xml, xml_ns.hf_tag); init_xml_parser(); + +} + +void add_dissector_media(gpointer k, gpointer v _U_, gpointer p _U_) { + dissector_add_string("media_type", (gchar*)k, xml_handle); } void @@ -595,33 +1104,6 @@ proto_reg_handoff_xml(void) xml_handle = find_dissector("xml"); - dissector_add_string("media_type", "text/xml", xml_handle); - dissector_add_string("media_type", "application/xml", xml_handle); - dissector_add_string("media_type", "application/soap+xml", xml_handle); - dissector_add_string("media_type", "application/xml-dtd", xml_handle); - /* WAP and OMA XML media */ - dissector_add_string("media_type", "text/vnd.wap.wml", xml_handle); - dissector_add_string("media_type", "text/vnd.wap.si", xml_handle); - dissector_add_string("media_type", "text/vnd.wap.sl", xml_handle); - dissector_add_string("media_type", "text/vnd.wap.co", xml_handle); - dissector_add_string("media_type", "text/vnd.wap.emn", xml_handle); - dissector_add_string("media_type", "application/vnd.wv.csp+xml", xml_handle); - /* The Extensible Markup Language (XML) Configuration Access Protocol (XCAP) - * draft-ietf-simple-xcap-06 - */ - dissector_add_string("media_type", "application/xcap-el+xml", xml_handle); - dissector_add_string("media_type", "application/xcap-att+xml", xml_handle); - dissector_add_string("media_type", "application/xcap-error+xml", xml_handle); - dissector_add_string("media_type", "application/xcap-caps+xml", xml_handle); - /* draft-ietf-simple-presence-rules-02 */ - dissector_add_string("media_type", "application/auth-policy+xml", xml_handle); - /* Other */ - dissector_add_string("media_type", "application/smil", xml_handle); - dissector_add_string("media_type", "application/cpim-pidf+xml", xml_handle); - dissector_add_string("media_type", "application/rdf+xml", xml_handle); - dissector_add_string("media_type", "application/xslt+xml", xml_handle); - dissector_add_string("media_type", "application/mathml+xml", xml_handle); - dissector_add_string("media_type", "image/svg+xml", xml_handle); - dissector_add_string("media_type", "application/vnd.wv.csp.xml", xml_handle); + g_hash_table_foreach(media_types,add_dissector_media,NULL); } |