1#
2# Wireshark Dissector Generator for SkinnyProtocolOptimized.xml
3#
4# Author: Diederik de Groot <ddegroot@user.sf.net>
5# Date: 2014-7-22
6# Skinny Protocol Versions: 0 through 22
7#
8# Heritage:
9# xml2obj based on https://code.activestate.com/recipes/149368-xml2obj/
10#
11# Dependencies:
12# python / xml / sax
13#
14# Called By:
15# cog.py + packet-skinny.c.in for inplace code generation
16# See: https://nedbatchelder.com/code/cog/
17#
18#
19# SPDX-License-Identifier: GPL-2.0-or-later
20#
21
22import re
23import xml.sax.handler
24
25indentation = 0
26indent_str = ''
27fieldsArray = {}
28si_fields = {
29    "callReference" : "si->callId",
30    "lineInstance": "si->lineId",
31    "passThroughPartyId" : "si->passThroughPartyId",
32    "callState" : "si->callState",
33    "callingParty" : "si->callingParty",
34    "calledParty" : "si->calledParty",
35    "mediaReceptionStatus" : "si->mediaReceptionStatus",
36    "mediaTransmissionStatus" : "si->mediaTransmissionStatus",
37    "multimediaReceptionStatus" : "si->multimediaReceptionStatus",
38    "multimediaTransmissionStatus" : "si->multimediaTransmissionStatus",
39    "multicastReceptionStatus" : "si->multicastReceptionStatus",
40}
41
42debug = 0
43
44def xml2obj(src):
45    """
46    A function to converts XML data into native Python objects.
47
48    """
49    non_id_char = re.compile('[^_0-9a-zA-Z]')
50
51    def _name_mangle(name):
52        return non_id_char.sub('_',
53    name)
54
55    class DataNode(object):
56        def __init__(self):
57            self._attrs = {}    # XML attributes and child elements
58            self.data = None    # child text data
59            self.parent = None
60            self.basemessage = None
61            self.intsize = 0
62            self._children = []
63            self.declared = []
64
65        def __len__(self):
66            # treat single element as a list of 1
67            return 1
68        def __getitem__(self, key):
69            if isinstance(key, basestring):
70                return self._attrs.get(key,None)
71            else:
72                return [self][key]
73
74        def __contains__(self, name):
75            return self._attrs.has_key(name)
76
77        def __nonzero__(self):
78            return bool(self._attrs or self.data)
79
80        def __getattr__(self, name):
81            if name.startswith('__'):
82                # need to do this for Python special methods???
83                raise AttributeError(name)
84            return self._attrs.get(name,None)
85
86        def _add_xml_attr(self, name, value):
87            if name in self._attrs:
88                # multiple attribute of the same name are represented by a list
89                children = self._attrs[name]
90                if not isinstance(children, list):
91                    children = [children]
92                    self._attrs[name] = children
93                children.append(value)
94            else:
95                self._attrs[name] = value
96
97        def _add_child(self, name, value):
98            #print "adding : %s / %s to %s" %(name,value, self.__class__)
99            self._children.append(value)
100
101        def __str__(self):
102            return '%s:%s' %(self.__class__,self.name)
103
104        def keys(self):
105            return self._attrs.keys()
106
107        def __repr__(self):
108            items = {}
109            if self.data:
110                items.append(('data', self.data))
111            return u'{%s}' % ', '.join([u'%s:%s' % (k,repr(v)) for k,v in items])
112
113        def __setitem__(self, key, value):
114            self._attrs[key] = value
115
116        def getfieldnames(self):
117            return ''
118
119        def get_req_resp_keys(self, req_resp_keys):
120            return []
121
122        def get_req_resp_key(self):
123            if self.req_resp_key == "1":
124                return self.name
125            return None
126
127        def declaration(self):
128            global fieldsArray
129            if self.name not in fieldsArray:
130                fieldsArray[self.name] = '/* UNKNOWN { &hf_skinny_%s,\n {\n"%s", "skinny.%s", FT_UINT32, BASE_DEC, NULL, 0x0,\n "%s", HFILL }}, */\n' %(self.name, self.name, self.name, self.comment)
131            return ''
132
133        def dissect(self):
134            return self.name or ''
135
136        def incr_indent(self):
137            global indentation
138            global indent_str
139            indentation += 1
140            indent_str = ''
141            for x in range(0, indentation):
142                indent_str += '  '
143
144        def decr_indent(self):
145            global indentation
146            global indent_str
147            indentation -= 1
148            indent_str = ''
149            for x in range(0, indentation):
150                indent_str += '  '
151
152        def indent_out(self, string):
153            return indent_str + string
154
155
156    class Message(DataNode):
157        ''' Message '''
158        def __str__(self):
159            return self.name
160
161        def gen_handler(self):
162            if self.fields is None:
163                # skip whole message and return NULL as handler
164                return 'NULL'
165            return 'handle_%s' %self.name
166
167        def dissect(self):
168            ret = ''
169            declarations = 0
170            fixed = 0
171
172            if (self.fields is not None):
173                ret += self.indent_out("/*\n")
174                ret += self.indent_out(" * Message:   %s\n" %self.name)
175                ret += self.indent_out(" * Opcode:    %s\n" %self.opcode)
176                ret += self.indent_out(" * Type:      %s\n" %self.type)
177                ret += self.indent_out(" * Direction: %s\n" %self.direction)
178                ret += self.indent_out(" * VarLength: %s\n" %self.dynamic)
179                ret += self.indent_out(" * MsgType:   %s\n" %self.msgtype)
180                if self.comment:
181                    ret += self.indent_out(" * Comment: %s\n" %self.comment)
182                ret += self.indent_out(" */\n")
183                ret += self.indent_out("static void\n")
184                ret += self.indent_out("handle_%s(ptvcursor_t *cursor, packet_info * pinfo _U_, skinny_conv_info_t * skinny_conv _U_)\n" %self.name)
185                ret += self.indent_out("{\n")
186                self.incr_indent()
187
188                for fields in self.fields:
189                    if fields.size_lt or fields.size_gt:
190                        if self.basemessage.declared is None or "hdr_data_length" not in self.basemessage.declared:
191                            ret += self.indent_out("guint32 hdr_data_length = tvb_get_letohl(ptvcursor_tvbuff(cursor), 0);\n")
192                            self.basemessage.declared.append("hdr_data_length")
193                            declarations += 1
194                    if fields.fixed == "yes":
195                        fixed = 1
196
197                if not declarations or fixed == 1:
198                    for fields in self.fields[1:]:
199                        if self.basemessage.declared is None or "hdr_version" not in self.basemessage.declared:
200                            ret += self.indent_out("guint32 hdr_version = tvb_get_letohl(ptvcursor_tvbuff(cursor), 4);\n")
201                            self.basemessage.declared.append("hdr_version")
202                            declarations += 1
203
204                req_resp_keys = []
205                for fields in self.fields:
206                    fields.get_req_resp_keys(req_resp_keys)
207                    ret += '%s' %fields.declaration()
208                    declarations += 1
209
210                if declarations > 1:
211                    ret += "\n"
212
213                if self.fields is not None:
214                    for fields in self.fields:
215                        ret += '%s' %fields.dissect()
216
217                # setup request/response
218                if self.msgtype == "request":
219                    if req_resp_keys and req_resp_keys[0] != '':
220                        ret += self.indent_out('skinny_reqrep_add_request(cursor, pinfo, skinny_conv, %s ^ %s);\n' %(self.opcode, req_resp_keys[0]))
221                    else:
222                        ret += self.indent_out('skinny_reqrep_add_request(cursor, pinfo, skinny_conv, %s);\n' %(self.opcode))
223
224                if self.msgtype == "response":
225                    if req_resp_keys and req_resp_keys[0] != '':
226                        ret += self.indent_out('skinny_reqrep_add_response(cursor, pinfo, skinny_conv, %s ^ %s);\n' %(self.request, req_resp_keys[0]))
227                    else:
228                        ret += self.indent_out('skinny_reqrep_add_response(cursor, pinfo, skinny_conv, %s);\n' %(self.request))
229
230                self.decr_indent()
231
232                ret += "}\n\n"
233            return ret
234
235    class Fields(DataNode):
236        ''' Fields '''
237        size_fieldnames= []
238
239        def get_req_resp_keys(self, req_resp):
240            for field in self._children:
241                key = field.get_req_resp_key()
242                if not key is None and not key in req_resp:
243                    req_resp.append(key)
244
245        def declaration(self):
246            ret = ''
247
248            for field in self._children:
249                ret += '%s' %(field.declaration())
250                self.intsize += field.intsize
251            return ret
252
253        def dissect(self, lookupguide=""):
254            ret = ''
255            ifstarted = 0
256            #ret += "/* [PARENT: %s, BASEMESSAGE: %s] */\n" %(self.parent.name,self.basemessage.name)
257
258            if ((self.beginversion or self.endversion) and (self.beginversion != "0" or self.endversion != "22")):
259
260                ifstarted = 1
261                ret += self.indent_out('if (')
262                if (self.beginversion and self.beginversion != "0"):
263                    if (not self.endversion or self.endversion == "22"):
264                        ret += 'hdr_version >= V%s_MSG_TYPE) {\n' %self.beginversion
265                    else:
266                        ret += 'hdr_version >= V%s_MSG_TYPE && ' %self.beginversion
267                if (self.endversion and self.endversion != "22"):
268                    ret += 'hdr_version <= V%s_MSG_TYPE) {\n' %self.endversion
269                self.incr_indent()
270
271            if self.size_lt:
272                ret += self.indent_out('if (hdr_data_length < %s) {\n' %self.size_lt)
273                self.incr_indent()
274
275            if self.size_gt:
276                ret += self.indent_out('if (hdr_data_length > %s) {\n' %self.size_gt)
277                self.incr_indent()
278
279            # generate dissection
280            for field in self._children:
281                ret += '%s' %(field.dissect())
282
283            if self.size_lt:
284                self.decr_indent()
285                ret += self.indent_out('}\n')
286
287            if self.size_gt:
288                self.decr_indent()
289                ret += self.indent_out('}\n')
290
291            if ifstarted:
292                self.decr_indent()
293                ret += self.indent_out('}\n')
294
295            return ret;
296
297    class Integer(DataNode):
298        def __init__(self):
299            DataNode.__init__(self)
300            self.intsize = 0
301            self.endian = "ENC_LITTLE_ENDIAN"
302
303        def __str__(self):
304            return '%s:%s' %(self.__class__,self.name)
305
306        def declaration(self):
307            ret = ''
308
309            int_sizes = {'uint32':4,'uint16':2,'uint8':1,'int32':4,'int16':2,'int8':1,'ipport':4}
310            if self.endianness == "big":
311                self.endian = "ENC_BIG_ENDIAN"
312            if self.type in int_sizes:
313                self.intsize = int_sizes[self.type]
314            else:
315                print("ERROR integer %s with type: %s, could not be found" %(self.name, self.type))
316
317            if self.declare == "yes" or self.make_additional_info == "yes":
318                if self.basemessage.declared is None or self.name not in self.basemessage.declared:
319                    ret += self.indent_out('guint%s %s = 0;\n' %(self.intsize * 8, self.name))
320                    self.basemessage.declared.append(self.name)
321
322            global fieldsArray
323            if self.name not in fieldsArray:
324                fieldsArray[self.name] ='{ &hf_skinny_%s,\n  {\n    "%s", "skinny.%s", FT_UINT%d, BASE_DEC, NULL, 0x0,\n    %s, HFILL }},\n' %(self.name, self.comment if (self.comment and self.longcomment) else self.name, self.name.replace("_","."), self.intsize * 8, '"' + self.longcomment + '"' if self.longcomment else '"' + self.comment + '"' if self.comment else 'NULL')
325            return ret
326
327        def dissect(self):
328            ret = ''
329
330            size = 0
331            if self.size_fieldname:
332                if self.basemessage.dynamic == "yes":
333                    size = self.size_fieldname
334                else:
335                    size = self.maxsize
336            elif self.size:
337                size = self.size
338
339            if size:
340                if self.size_fieldname:
341                    ret += self.indent_out('if (%s <= %s) {%s\n' %(self.size_fieldname, size, ' /* tvb integer size guard */' if debug else ''))
342                else:
343                    ret += self.indent_out('{\n')
344                self.incr_indent()
345                variable = 'counter_%d' %indentation
346                ret += self.indent_out('guint32 %s = 0;\n' %(variable));
347                if self.size_fieldname:
348                    ret += self.indent_out('ptvcursor_add_text_with_subtree(cursor, SUBTREE_UNDEFINED_LENGTH, ett_skinny_tree, "%s [ref:%s = %%d, max:%s]", %s);\n' %(self.name, self.size_fieldname, size, self.size_fieldname))
349                else:
350                    ret += self.indent_out('ptvcursor_add_text_with_subtree(cursor, SUBTREE_UNDEFINED_LENGTH, ett_skinny_tree, "%s [max:%s]");\n' %(self.name, size))
351                ret += self.indent_out('for (%s = 0; %s < %s; %s++) {\n' %(variable, variable, size, variable));
352                if self.basemessage.dynamic == "no" and self.size_fieldname:
353                    self.incr_indent()
354                    ret += self.indent_out('if (%s < %s) {\n' %(variable,self.size_fieldname))
355                self.incr_indent()
356
357            if self.declare == "yes" or self.make_additional_info == "yes":
358                if self.endianness == "big":
359                    if (self.intsize == 4):
360                        ret += self.indent_out('%s = tvb_get_ntohl(ptvcursor_tvbuff(cursor), ptvcursor_current_offset(cursor));\n' %(self.name))
361                    elif (self.intsize == 2):
362                        ret += self.indent_out('%s = tvb_get_ntohs(ptvcursor_tvbuff(cursor), ptvcursor_current_offset(cursor));\n' %(self.name))
363                    else:
364                        ret += self.indent_out('%s = tvb_get_guint8(ptvcursor_tvbuff(cursor), ptvcursor_current_offset(cursor));\n' %(self.name))
365                else:
366                    if (self.intsize == 4):
367                        ret += self.indent_out('%s = tvb_get_letohl(ptvcursor_tvbuff(cursor), ptvcursor_current_offset(cursor));\n' %(self.name))
368                    elif (self.intsize == 2):
369                        ret += self.indent_out('%s = tvb_get_letohs(ptvcursor_tvbuff(cursor), ptvcursor_current_offset(cursor));\n' %(self.name))
370                    else:
371                        ret += self.indent_out('%s = tvb_get_guint8(ptvcursor_tvbuff(cursor), ptvcursor_current_offset(cursor));\n' %(self.name))
372
373            if self.name in si_fields.keys():
374                if self.endianness == "big":
375                    ret += self.indent_out('%s = tvb_get_ntohs(ptvcursor_tvbuff(cursor), ptvcursor_current_offset(cursor));\n' %(si_fields[self.name]))
376                else:
377                    ret += self.indent_out('%s = tvb_get_letohl(ptvcursor_tvbuff(cursor), ptvcursor_current_offset(cursor));\n' %(si_fields[self.name]))
378
379            ret += self.indent_out('ptvcursor_add(cursor, hf_skinny_%s, %d, %s);\n' %(self.name, self.intsize, self.endian))
380
381            if size:
382                if self.basemessage.dynamic == "no" and self.size_fieldname:
383                    self.decr_indent()
384                    ret += self.indent_out('} else {\n')
385                    ret += self.indent_out('  ptvcursor_advance(cursor, %d);\n' %self.intsize)
386                    ret += self.indent_out('}\n')
387                self.decr_indent()
388                ret += self.indent_out('}\n')
389                if debug:
390                    ret += self.indent_out('ptvcursor_pop_subtree(cursor); /* end for loop tree: %s */\n' %(self.name))
391                else:
392                    ret += self.indent_out('ptvcursor_pop_subtree(cursor);\n')
393                self.decr_indent()
394                if self.size_fieldname:
395                    ret += self.indent_out('} else {\n')
396                    self.incr_indent()
397                    ret += self.indent_out('ptvcursor_advance(cursor, (%s * %s));%s\n' %(size, self.intsize, ' /* guard kicked in -> skip the rest */;' if debug else ''))
398                    self.decr_indent()
399                ret += self.indent_out('}\n')
400
401            if self.make_additional_info == "yes":
402                ret += self.indent_out('srtp_add_address(pinfo, PT_UDP, &%s, %s, 0, "SKINNY", pinfo->num, false, NULL, NULL, NULL);\n' %(self.use_param, self.name))
403                ret += self.indent_out('%s_str = address_to_display(NULL, &%s);\n' % (self.use_param, self.use_param))
404                ret += self.indent_out('si->additionalInfo = g_strdup_printf("%%s:%%d", %s_str, %s);\n' % (self.use_param, self.name))
405                ret += self.indent_out('wmem_free(NULL, %s_str);\n' % (self.use_param))
406
407            return ret
408
409    class Enum(DataNode):
410        def __init__(self):
411            DataNode.__init__(self)
412            self.intsize = 0
413            self.sparse = 0
414
415        def __str__(self):
416            return '%s:%s' %(self.__class__,self.name)
417
418        def declaration(self):
419            ret = ''
420            prevvalue = 0
421            enum_sizes = {'uint32':4,'uint16':2,'uint8':1}
422            if self.type in enum_sizes:
423                self.intsize = enum_sizes[self.type]
424            else:
425                print("ERROR enum %s with type: %s, could not be found" %(self.name, self.type))
426
427            if self.declare == "yes":
428                if self.basemessage.declared is None or self.name not in self.basemessage.declared:
429                    ret += self.indent_out('g%s %s = 0;\n' %(self.type, self.name))
430                    self.basemessage.declared.append(self.name)
431
432            global fieldsArray
433            if self.name not in fieldsArray:
434                fieldsArray[self.name] ='{&hf_skinny_%s,\n  {\n    "%s", "skinny.%s", FT_UINT%d, BASE_HEX | BASE_EXT_STRING, &%s_ext, 0x0,\n    %s, HFILL }},\n' %(self.name, self.comment if (self.comment and self.longcomment) else self.name, self.name.replace("_","."), self.intsize * 8, self.subtype[0].upper() + self.subtype[1:], '"' + self.longcomment + '"' if self.longcomment else '"' + self.comment + '"' if self.comment else 'NULL')
435            return ret
436
437        def dissect(self):
438            ret = ''
439            endian = "ENC_LITTLE_ENDIAN"
440            size = 0
441            if self.size_fieldname:
442                if self.basemessage.dynamic == "yes":
443                    size = self.size_fieldname
444                else:
445                    size = self.maxsize
446            elif self.size:
447                size = self.size
448
449            if self.make_additional_info == "yes":
450                ret += self.indent_out('si->additionalInfo = g_strdup_printf("\\"%s\\"",\n')
451                self.incr_indent()
452                ret += self.indent_out('try_val_to_str_ext(\n')
453                self.incr_indent()
454                ret += self.indent_out('tvb_get_letohl(ptvcursor_tvbuff(cursor), ptvcursor_current_offset(cursor)),\n')
455                ret += self.indent_out('&%s_ext\n' %(self.subtype[0].upper() + self.subtype[1:]))
456                self.decr_indent()
457                ret += self.indent_out(')\n')
458                self.decr_indent()
459                ret += self.indent_out(');\n')
460
461            if self.make_additional_info_short == "yes":
462                ret += self.indent_out('si->additionalInfo = g_strdup_printf("\\"%s\\"",\n')
463                self.incr_indent()
464                ret += self.indent_out('try_val_to_str_ext(\n')
465                self.incr_indent()
466                ret += self.indent_out('tvb_get_letohl(ptvcursor_tvbuff(cursor), ptvcursor_current_offset(cursor)),\n')
467                ret += self.indent_out('&%s_short_ext\n' %(self.subtype[0].upper() + self.subtype[1:]))
468                self.decr_indent()
469                ret += self.indent_out(')\n')
470                self.decr_indent()
471                ret += self.indent_out(');\n')
472
473            if size:
474                if self.size_fieldname:
475                    ret += self.indent_out('if (%s <= %s) { /* tvb enum size guard */\n' %(self.size_fieldname, self.maxsize))
476                else:
477                    ret += self.indent_out('{\n')
478                self.incr_indent()
479                variable = 'counter_%d' %indentation
480                ret += self.indent_out('guint32 %s = 0;\n' %(variable));
481                if self.size_fieldname:
482                    ret += self.indent_out('ptvcursor_add_text_with_subtree(cursor, SUBTREE_UNDEFINED_LENGTH, ett_skinny_tree, "%s [ref: %s = %%d, max:%s]", %s);\n' %(self.name, self.size_fieldname, size, self.size_fieldname))
483                else:
484                    ret += self.indent_out('ptvcursor_add_text_with_subtree(cursor, SUBTREE_UNDEFINED_LENGTH, ett_skinny_tree, "%s [max:%s]");\n' %(self.name, size))
485                ret += self.indent_out('for (%s = 0; %s < %s; %s++) {\n' %(variable, variable, size, variable));
486                if self.basemessage.dynamic == "no" and self.size_fieldname:
487                    self.incr_indent()
488                    ret += self.indent_out('if (%s < %s) {\n' %(variable,self.size_fieldname))
489                self.incr_indent()
490
491            if self.name in si_fields.keys():
492                ret += self.indent_out('%s = tvb_get_letohl(ptvcursor_tvbuff(cursor), ptvcursor_current_offset(cursor));\n' %(si_fields[self.name]))
493
494            if self.declare == "yes":
495                if (self.intsize == 4):
496                    ret += self.indent_out('%s = tvb_get_letohl(ptvcursor_tvbuff(cursor), ptvcursor_current_offset(cursor));\n' %(self.name))
497                elif (self.intsize == 2):
498                    ret += self.indent_out('%s = tvb_get_letohs(ptvcursor_tvbuff(cursor), ptvcursor_current_offset(cursor));\n' %(self.name))
499                else:
500                    ret += self.indent_out('%s = tvb_get_guint8(ptvcursor_tvbuff(cursor), ptvcursor_current_offset(cursor));\n' %(self.name))
501
502            ret += self.indent_out('ptvcursor_add(cursor, hf_skinny_%s, %d, %s);\n' %(self.name, self.intsize, endian))
503
504            if size:
505                if self.basemessage.dynamic == "no" and self.size_fieldname:
506                    self.decr_indent()
507                    ret += self.indent_out('} else {\n')
508                    ret += self.indent_out('  ptvcursor_advance(cursor, 4);\n')
509                    ret += self.indent_out('}\n')
510                self.decr_indent()
511                ret += self.indent_out('}\n')
512                if debug:
513                    ret += self.indent_out('ptvcursor_pop_subtree(cursor); /* end for loop tree: %s */\n' %(self.name))
514                else:
515                    ret += self.indent_out('ptvcursor_pop_subtree(cursor);\n')
516                self.decr_indent()
517                if self.size_fieldname:
518                    ret += self.indent_out('} else {\n')
519                    self.incr_indent()
520                    ret += self.indent_out('ptvcursor_advance(cursor, (%s * %s)); /* guard kicked in -> skip the rest */;\n' %(size, self.intsize))
521                    self.decr_indent()
522                ret += self.indent_out('}\n')
523
524            return ret
525
526    class String(DataNode):
527        def __init__(self):
528            DataNode.__init__(self)
529
530        def __str__(self):
531            return '%s:%s' %(self.__class__,self.name)
532
533        def get_req_resp_key(self):
534            if self.req_resp_key == "1":
535                return 'wmem_str_hash(%s)' %self.name
536            return None
537
538        def declaration(self):
539            ret = ''
540            self.intsize = 0
541            if self.size:
542                if self.size=="VariableDirnumSize":
543                    self.intsize = 24
544                else:
545                    self.intsize = int(self.size)
546            elif self.maxsize and self.basemessage.dynamic == "no":
547                self.intsize = int(self.maxsize)
548
549            if self.declare == "yes":
550                if self.size=="VariableDirnumSize":
551                    if self.basemessage.declared is None or "VariableDirnumSize" not in self.basemessage.declared:
552                        if self.basemessage.declared is None or "hdr_version" not in self.basemessage.declared:
553                        #if (self.basemessage.fields is not None and len(self.basemessage.fields) == 1):
554                            ret += self.indent_out('guint32 hdr_version = tvb_get_letohl(ptvcursor_tvbuff(cursor), 4);\n')
555                            self.basemessage.declared.append("hdr_version")
556                        ret += self.indent_out('guint32 VariableDirnumSize = (hdr_version >= V18_MSG_TYPE) ? 25 : 24;\n')
557                        self.basemessage.declared.append("VariableDirnumSize")
558                #else:
559                #    if self.basemessage.declared is None or self.name not in self.basemessage.declared:
560                #        ret += self.indent_out('gchar *%s = NULL;\n' %self.name)
561                #        self.basemessage.declared.append(self.name)
562
563            if self.basemessage.dynamic == "yes" and not self.subtype == "DisplayLabel":
564                if self.basemessage.declared is None or self.name + '_len' not in self.basemessage.declared:
565                    ret += self.indent_out('guint32 %s_len = 0;\n' %self.name)
566                    self.basemessage.declared.append(self.name + '_len')
567
568            global fieldsArray
569            if self.name not in fieldsArray:
570                fieldsArray[self.name] = '{&hf_skinny_%s,\n  {\n    "%s", "skinny.%s", FT_STRING, BASE_NONE, NULL, 0x0,\n    %s, HFILL }},\n' %(self.name, self.comment if (self.comment and self.longcomment) else self.name, self.name.replace("_","."), '"' + self.longcomment + '"' if self.longcomment else '"' + self.comment + '"' if self.comment else 'NULL')
571            return ret
572
573        def dissect(self):
574            ret = ''
575
576            if self.declare == "yes" and self.size != "VariableDirnumSize":
577                ret += self.indent_out('const gchar * %s = g_strdup(tvb_format_stringzpad(pinfo->pool, ptvcursor_tvbuff(cursor), ptvcursor_current_offset(cursor), %s));\n' %(self.name, self.size))
578
579            if self.subtype == "DisplayLabel":
580                if self.basemessage.dynamic == "yes":
581                    ret += self.indent_out('dissect_skinny_displayLabel(cursor, pinfo, hf_skinny_%s, 0);\n' %(self.name))
582                elif self.size_fieldname:
583                    ret += self.indent_out('dissect_skinny_displayLabel(cursor, pinfo, hf_skinny_%s, %s);\n' %(self.name, self.size_fieldname))
584                else:
585                    ret += self.indent_out('dissect_skinny_displayLabel(cursor, pinfo, hf_skinny_%s, %s);\n' %(self.name, self.size))
586
587            elif self.basemessage.dynamic == "yes":
588                ret += self.indent_out('%s_len = tvb_strnlen(ptvcursor_tvbuff(cursor), ptvcursor_current_offset(cursor), -1)+1;\n' %self.name)
589                ret += self.indent_out('if (%s_len > 1) {\n' %self.name)
590                if self.name in si_fields.keys():
591                    ret += self.indent_out('  %s = g_strdup(tvb_format_stringzpad(pinfo->pool, ptvcursor_tvbuff(cursor), ptvcursor_current_offset(cursor), %s_len));\n' %(si_fields[self.name], self.name))
592                ret += self.indent_out('  ptvcursor_add(cursor, hf_skinny_%s, %s_len, ENC_ASCII|ENC_NA);\n' %(self.name, self.name))
593                ret += self.indent_out('} else {\n')
594                ret += self.indent_out('  ptvcursor_advance(cursor, 1);\n')
595                ret += self.indent_out('}\n')
596            elif self.size_fieldname:
597                if self.name in si_fields.keys():
598                    ret += self.indent_out('%s = g_strdup(tvb_format_stringzpad(pinfo->pool, ptvcursor_tvbuff(cursor), ptvcursor_current_offset(cursor), %s));\n' %(si_fields[self.name], self.size_fieldname))
599                ret += self.indent_out('ptvcursor_add(cursor, hf_skinny_%s, %s, ENC_ASCII|ENC_NA);\n' %(self.name, self.size_fieldname))
600            else:
601                if self.name in si_fields.keys():
602                    ret += self.indent_out('%s = g_strdup(tvb_format_stringzpad(pinfo->pool, ptvcursor_tvbuff(cursor), ptvcursor_current_offset(cursor), %s));\n' %(si_fields[self.name], self.size))
603                if self.make_additional_info == "yes":
604                    ret += self.indent_out('guint32 %s_len;\n' %(self.name))
605                    if self.size=="VariableDirnumSize":
606                        ret += self.indent_out('%s_len = tvb_strnlen(ptvcursor_tvbuff(cursor), ptvcursor_current_offset(cursor), VariableDirnumSize)+1;\n' %(self.name))
607                    else:
608                        ret += self.indent_out('%s_len = tvb_strnlen(ptvcursor_tvbuff(cursor), ptvcursor_current_offset(cursor), 24)+1;\n' %(self.name))
609                    ret += self.indent_out('if (%s_len > 1) {\n' %(self.name))
610                    self.incr_indent()
611                    ret += self.indent_out('si->additionalInfo = g_strdup_printf("\\"%%s\\"", tvb_format_stringzpad(pinfo->pool, ptvcursor_tvbuff(cursor), ptvcursor_current_offset(cursor), %s_len));\n' %(self.name))
612                    self.decr_indent()
613                    ret += self.indent_out('}\n')
614
615                ret += self.indent_out('ptvcursor_add(cursor, hf_skinny_%s, %s, ENC_ASCII|ENC_NA);\n' %(self.name, self.size))
616
617            return ret
618
619    class Ether(DataNode):
620        def __init__(self):
621            DataNode.__init__(self)
622
623        def __str__(self):
624            return '%s:%s' %(self.__class__,self.name)
625
626        def declaration(self):
627            ret = ''
628            self.intsize = 6
629            if self.size:
630                self.intsize = int(self.size)
631            elif self.maxsize and self.basemessage.dynamic == "no":
632                self.intsize = int(self.maxsize)
633
634            if self.declare == "yes":
635                if self.basemessage.declared is None or self.name not in self.basemessage.declared:
636                    ret += self.indent_out('guint32 %s = 0;\n' %self.name)
637                    self.basemessage.declared.append(self.name)
638
639            if self.basemessage.dynamic == "yes":
640                if self.basemessage.declared is None or self.name + '_len' not in self.basemessage.declared:
641                    ret += self.indent_out('guint32 %s_len = 0;\n' %self.name)
642                    self.basemessage.declared.append(self.name + '_len')
643
644            global fieldsArray
645            if self.name not in fieldsArray:
646                fieldsArray[self.name] = '{ &hf_skinny_%s,\n  {\n    "%s", "skinny.%s", FT_ETHER, BASE_NONE, NULL, 0x0,\n    %s, HFILL }},\n' %(self.name, self.comment if (self.comment and self.longcomment) else self.name, self.name.replace("_","."), '"' + self.longcomment + '"' if self.longcomment else '"' + self.comment + '"' if self.comment else 'NULL')
647            return ret
648
649        def dissect(self):
650            ret = ''
651
652            if self.basemessage.dynamic == "yes":
653                ret += self.indent_out('%s_len = tvb_strnlen(ptvcursor_tvbuff(cursor), ptvcursor_current_offset(cursor), -1)+1;\n' %self.name)
654                ret += self.indent_out('if (%s_len > 1) {\n' %self.name)
655                ret += self.indent_out('  ptvcursor_add(cursor, hf_skinny_%s, 6, ENC_NA);\n' %(self.name, self.name))
656                ret += self.indent_out('  ptvcursor_advance(cursor, %s_len - 6);\n' %(self.name))
657                ret += self.indent_out('} else {\n')
658                ret += self.indent_out('  ptvcursor_advance(cursor, 1);\n')
659                ret += self.indent_out('}\n')
660            elif self.size_fieldname:
661                ret += self.indent_out('ptvcursor_add(cursor, hf_skinny_%s, 6, ENC_NA);\n' %(self.name))
662                ret += self.indent_out('ptvcursor_advance(cursor, %s - 6);\n' %(self.size_fieldname))
663            else:
664                ret += self.indent_out('ptvcursor_add(cursor, hf_skinny_%s, 6, ENC_NA);\n' %(self.name))
665                ret += self.indent_out('ptvcursor_advance(cursor, %s - 6);\n' %(self.size))
666            return ret
667
668    class BitField(DataNode):
669        def __init__(self):
670            DataNode.__init__(self)
671
672        def __str__(self):
673            return '%s:%s' %(self.__class__,self.name)
674
675        def declaration(self):
676            global fieldsArray
677            ret = ''
678            int_sizes = {'uint32':4,'uint16':2,'uint8':1,'int32':4,'int16':2,'int8':1}
679            self.intsize = 0
680            if self.size in int_sizes:
681                self.intsize = int_sizes[self.size]
682
683            for entries in self.entries:
684                for entry in entries.entry:
685                    if entry.name not in fieldsArray:
686                        fieldsArray[entry.name] = '{ &hf_skinny_%s,\n  {\n    "%s", "skinny.%s", FT_BOOLEAN, %d, TFS(&tfs_yes_no), %s,\n    %s, HFILL }},\n' %(entry.name, entry.text, entry.name.replace("_","."), self.intsize * 8, entry.value, '"' + self.longcomment + '"' if self.longcomment else '"' + self.comment + '"' if self.comment else 'NULL')
687
688            return ret
689
690        def dissect(self):
691            ret = ''
692            ret += self.indent_out('ptvcursor_add_text_with_subtree(cursor, SUBTREE_UNDEFINED_LENGTH, ett_skinny_tree, "%s");\n' %(self.name))
693            for entries in self.entries:
694                for entry in entries.entry:
695                    ret += self.indent_out('ptvcursor_add_no_advance(cursor, hf_skinny_%s, %d, ENC_LITTLE_ENDIAN);\n' %(entry.name, self.intsize))
696            ret += self.indent_out('ptvcursor_advance(cursor, %d);\n' %(self.intsize))
697            ret += self.indent_out('ptvcursor_pop_subtree(cursor); /* end bitfield: %s */\n' %(self.name))
698
699
700            return ret
701
702    class Ip(DataNode):
703        def __init__(self):
704            DataNode.__init__(self)
705            self.intsize = 4
706            if self.type == "ipv6":
707                self.intsize = 16
708
709        def __str__(self):
710            return '%s:%s' %(self.__class__,self.name)
711
712        def declaration(self):
713            global fieldsArray
714            if self.name not in fieldsArray:
715                if self.type == "ipv4":
716                    fieldsArray[self.name] = '{ &hf_skinny_%s,\n  {\n    "%s", "skinny.%s", FT_IPv4, BASE_NONE, NULL, 0x0,\n    %s, HFILL }},\n' %(self.name, self.comment if (self.comment and self.longcomment) else self.name, self.name.replace("_","."), '"' + self.longcomment + '"' if self.longcomment else '"' + self.comment + '"' if self.comment else 'NULL')
717                else:
718                    fieldsArray[self.name] = '{ &hf_skinny_%s,\n  {\n    "%s", "skinny.%s", FT_IPv6, BASE_NONE, NULL, 0x0,\n    %s, HFILL }},\n' %(self.name, self.comment if (self.comment and self.longcomment) else self.name, self.name.replace("_","."), '"' + self.longcomment + '"' if self.longcomment else '"' + self.comment + '"' if self.comment else 'NULL')
719            return ''
720
721        def dissect(self):
722            if self.type == "ipv4":
723                return self.indent_out('ptvcursor_add(cursor, hf_skinny_%s, 4, ENC_BIG_ENDIAN);\n' %self.name)
724            else:
725                return self.indent_out('ptvcursor_add(cursor, hf_skinny_%s, 16, ENC_NA);\n' %self.name)
726
727    class Ipv4or6(DataNode):
728        def __init__(self):
729            DataNode.__init__(self)
730            self.intsize = 4
731            if self.endianness is None:
732                self.intsize += 16
733
734        def __str__(self):
735            return '%s:%s' %(self.__class__,self.name)
736
737        def declaration(self):
738            global fieldsArray
739
740            ret = ''
741            name = self.name + '_ipv4'
742            if name not in fieldsArray:
743                fieldsArray[name] = '{ &hf_skinny_%s,\n {\n    "%s", "skinny.%s", FT_IPv4, BASE_NONE, NULL, 0x0,\n    %s, HFILL }},\n' %(name, self.name + ' IPv4 Address', name.replace("_","."), '"' + self.longcomment + '"' if self.longcomment else '"' + self.comment + '"' if self.comment else 'NULL')
744            name = self.name + '_ipv6'
745            if name not in fieldsArray:
746                fieldsArray[name] = '{ &hf_skinny_%s,\n {\n    "%s", "skinny.%s", FT_IPv6, BASE_NONE, NULL, 0x0,\n    %s, HFILL }},\n' %(name, self.name + ' IPv6 Address', name.replace("_","."), '"' + self.longcomment + '"' if self.longcomment else '"' + self.comment + '"' if self.comment else 'NULL')
747            if self.make_additional_info == "yes":
748                if self.basemessage.declared is None or self.name not in self.basemessage.declared:
749                    ret += self.indent_out('address %s;\n' %(self.name))
750                    ret += self.indent_out('char *%s_str = NULL;\n' %(self.name))
751                    self.basemessage.declared.append(self.name)
752
753            return ret
754
755        def dissect(self):
756            ret = ''
757            if self.make_additional_info == "yes":
758                ret += self.indent_out('read_skinny_ipv4or6(cursor, &%s);\n' %(self.name));
759            ret += self.indent_out('dissect_skinny_ipv4or6(cursor, hf_skinny_%s_ipv4, hf_skinny_%s_ipv6);\n' %(self.name, self.name));
760            return ret;
761
762    class XML(DataNode):
763        def __init__(self):
764            DataNode.__init__(self)
765            self.intsize = 0
766
767        def __str__(self):
768            return '%s:%s' %(self.__class__,self.name)
769
770        def declaration(self):
771            global fieldsArray
772
773            if self.size:
774                self.intsize = int(self.size)
775            elif self.maxsize:
776                self.intsize = int(self.maxsize)
777
778            if self.name not in fieldsArray:
779                fieldsArray[self.name] = '{ &hf_skinny_%s,\n  {\n    "%s", "skinny.%s", FT_STRING, BASE_NONE, NULL, 0x0,\n    %s, HFILL }},\n' %(self.name, self.comment if (self.comment and self.longcomment) else self.name, self.name.replace("_","."), '"' + self.longcomment + '"' if self.longcomment else '"' + self.comment + '"' if self.comment else 'NULL')
780            return ''
781
782        def dissect(self):
783            ret = ''
784            if self.size_fieldname:
785                ret += self.indent_out('dissect_skinny_xml(cursor, hf_skinny_%s, pinfo, %s, %d);\n' %(self.name, self.size_fieldname, self.intsize))
786            else:
787                ret += self.indent_out('dissect_skinny_xml(cursor, hf_skinny_%s, pinfo, 0, %d);\n' %(self.name, self.intsize))
788            return ret
789
790    class Code(DataNode):
791        def __init__(self):
792            DataNode.__init__(self)
793
794        def __str__(self):
795            return '%s:%s' %(self.__class__,self.name)
796
797        def declaration(self):
798            return ''
799
800        def dissect(self):
801            ret = ''
802            if self.type == "calling_and_called_party":
803                params = self.use_param.split(',')
804                ret += self.indent_out('if (si->%s && si->%s) {\n' %(params[0], params[1]))
805                self.incr_indent()
806                ret += self.indent_out('si->additionalInfo = g_strdup_printf("\\"%%s -> %%s\\"", si->%s, si->%s);\n' %(params[0], params[1]))
807                self.decr_indent()
808                ret += self.indent_out('}\n')
809            return ret
810
811    class Struct(DataNode):
812        def __str__(self):
813            return '// Struct : %s / %s / %s / %s\n' %(self.name, self.size, self.field_sizename, self.maxsize)
814
815        def declaration(self):
816            ret = ''
817
818            if (self.fields is not None and len(self.fields)):
819                if (len(self.fields) > 1):
820                    if self.basemessage.declared is None or "hdr_version" not in self.basemessage.declared:
821                        ret += self.indent_out("guint32 hdr_version = tvb_get_letohl(ptvcursor_tvbuff(cursor), 4);\n")
822                        self.basemessage.declared.append("hdr_version")
823                for fields in self.fields:
824                    ret += '%s' %fields.declaration()
825                    #self.intsize += fields.intsize
826                    self.intsize = fields.intsize
827            return ret
828
829        def dissect(self):
830            ret = ''
831            variable = 'counter_%d' %indentation
832            size = 0
833
834            if self.size_fieldname:
835                #if self.basemessage.dynamic == "yes":
836                #    size = self.size_fieldname
837                #else:
838                #    size = self.maxsize
839                size = self.maxsize
840            elif self.size:
841                size = self.size
842
843            if size:
844                if self.size_fieldname:
845                    ret += self.indent_out('if (%s <= %s) {%s\n' %(self.size_fieldname, size, ' /* tvb struct size guard */' if debug else ''))
846                else:
847                    ret += self.indent_out('{\n')
848                self.incr_indent()
849                if debug:
850                    ret += self.indent_out('/* start struct : %s / size: %d */\n' %(self.name, self.intsize))
851                ret += self.indent_out('guint32 %s = 0;\n' %(variable));
852                if self.size_fieldname:
853                    ret += self.indent_out('ptvcursor_add_text_with_subtree(cursor, SUBTREE_UNDEFINED_LENGTH, ett_skinny_tree, "%s [ref:%s = %%d, max:%s]", %s);\n' %(self.name, self.size_fieldname, self.maxsize, self.size_fieldname))
854                    if self.maxsize:
855                        ret += self.indent_out('if (%s && tvb_get_letohl(ptvcursor_tvbuff(cursor), 0) + 8 >= ptvcursor_current_offset(cursor) + (%s * %s) && %s <= %s) {%s\n' %(self.size_fieldname, self.size_fieldname, self.intsize, self.size_fieldname, self.maxsize, '/* tvb counter size guard */' if debug else ''))
856                    else:
857                        ret += self.indent_out('if (%s && tvb_get_letohl(ptvcursor_tvbuff(cursor), 0) + 8 >= ptvcursor_current_offset(cursor) + (%s * %s)) {%s\n' %(self.size_fieldname, self.size_fieldname, self.intsize, '/* tvb counter size guard */' if debug else ''))
858                    self.incr_indent()
859                else:
860                    ret += self.indent_out('ptvcursor_add_text_with_subtree(cursor, SUBTREE_UNDEFINED_LENGTH, ett_skinny_tree, "%s [max:%s]");\n' %(self.name, size))
861
862                ret += self.indent_out('for (%s = 0; %s < %s; %s++) {\n' %(variable, variable, size, variable));
863                if self.basemessage.dynamic == "no" and self.size_fieldname:
864                    self.incr_indent()
865                    ret += self.indent_out('if (%s < %s) {\n' %(variable,self.size_fieldname))
866                self.incr_indent()
867            else:
868                if debug:
869                    ret += self.indent_out('{ /* start struct : %s / size: %d */\n' %(self.name, self.intsize))
870                else:
871                    ret += self.indent_out('{\n')
872                self.incr_indent()
873                ret += self.indent_out('ptvcursor_add_text_with_subtree(cursor, SUBTREE_UNDEFINED_LENGTH, ett_skinny_tree, "%s");\n' %(self.name))
874
875            if size:
876                if self.size_fieldname:
877                    ret += self.indent_out('ptvcursor_add_text_with_subtree(cursor, SUBTREE_UNDEFINED_LENGTH, ett_skinny_tree, "%s [%%d / %%d]", %s + 1, %s);\n' %(self.name, variable, self.size_fieldname))
878                else:
879                    ret += self.indent_out('ptvcursor_add_text_with_subtree(cursor, SUBTREE_UNDEFINED_LENGTH, ett_skinny_tree, "%s [%%d / %%d]", %s + 1, %s);\n' %(self.name, variable, size))
880
881            if (self.fields is not None and len(self.fields)):
882                for fields in self.fields:
883                    ret += '%s' %fields.dissect()
884
885            if self.basemessage.dynamic == "no" and self.size_fieldname:
886                self.decr_indent()
887                ret += self.indent_out('} else {\n')
888                ret += self.indent_out('  ptvcursor_advance(cursor, %d);\n' %(self.intsize))
889                ret += self.indent_out('}\n')
890
891            if size:
892                ret += self.indent_out('ptvcursor_pop_subtree(cursor);\n')
893                self.decr_indent()
894                if debug:
895                    ret += self.indent_out('} /* end for loop tree: %s */\n' %self.name)
896                else:
897                    ret += self.indent_out('}\n')
898                if self.size_fieldname:
899                    self.decr_indent()
900                    ret += self.indent_out('} /* end counter tvb size guard */\n' if debug else '}\n')
901
902            ret += self.indent_out('ptvcursor_pop_subtree(cursor);\n')
903            if debug:
904                ret += self.indent_out('/* end struct: %s */\n' %self.name)
905            self.decr_indent()
906            if self.size_fieldname:
907                ret += self.indent_out('} else {\n')
908                self.incr_indent()
909                ret += self.indent_out('ptvcursor_advance(cursor, (%s * %s));%s\n' %(self.size_fieldname, self.intsize, ' /* guard kicked in -> skip the rest */' if debug else ''));
910                self.decr_indent()
911            ret += self.indent_out('} /* end struct size guard */\n' if debug else '}\n')
912
913            return ret
914
915    class Union(DataNode):
916        def __str__(self):
917            return '%s:%s' %(self.__class__,self.name)
918
919        def declaration(self):
920            ret = ''
921            self.maxsize = 0
922            if (self.fields is not None and len(self.fields)):
923                if (len(self.fields) > 1):
924                    if self.basemessage.declared is None or "hdr_version" not in self.basemessage.declared:
925                        ret += self.indent_out("guint32 hdr_version = tvb_get_letohl(ptvcursor_tvbuff(cursor), 4);\n")
926                        self.basemessage.declared.append("hdr_version")
927                for fields in self.fields:
928                    ret += '%s' %fields.declaration()
929                    previous_lookup_eq = fields._children[0].lookup_eq
930                    previous_lookup_le = fields._children[0].lookup_le
931                    previous_lookup_ge = fields._children[0].lookup_ge
932                    self.runningtotal = 0
933                    for field in fields._children:
934                        if previous_lookup_eq != field.lookup_eq or previous_lookup_le != field.lookup_le or previous_lookup_ge == field.lookup_ge:
935                            previous_lookup_eq = field.lookup_eq
936                            previous_lookup_le = field.lookup_le
937                            previous_lookup_ge = field.lookup_ge
938                            self.runningtotal = 0
939
940                        self.runningtotal += field.intsize
941                        if self.runningtotal > self.maxsize:
942                            self.maxsize = self.runningtotal
943
944            self.intsize = self.maxsize
945
946            return ret
947
948        def dissect(self):
949            ret = ''
950            ifblock = self.indent_out('if')
951            skip = 0
952            #ret += self.indent_out('/* Union : %s / maxsize: %s */\n' %(self.name, self.maxsize))
953
954            if (self.fields is not None and len(self.fields)):
955                for fields in self.fields:
956                    for field in fields._children:
957                        if self.lookup_guide and (field.lookup_ge or field.lookup_le or field.lookup_eq):
958                            lookupguide = self.lookup_guide
959                            # start block
960                            subtree_text = ''
961                            if field.lookup_ge and field.lookup_le:
962                                ret += '%s (%s >= %s && %s <= %s)' %(ifblock, lookupguide, field.lookup_ge.upper(), lookupguide, field.lookup_le.upper())
963                                subtree_text = "%s <= %s <= %s" %(field.lookup_ge, lookupguide, field.lookup_le)
964                            elif field.lookup_ge:
965                                ret += '%s (%s >= %s)' %(ifblock, lookupguide, field.lookup_ge.upper())
966                                subtree_text = "%s >= %s" %(lookupguide, field.lookup_ge)
967                            elif field.lookup_le:
968                                ret += '%s (%s <= %s)' %(ifblock, lookupguide, field.lookup_le.upper())
969                                subtree_text = "%s <= %s" %(lookupguide, field.lookup_le)
970                            elif field.lookup_eq:
971                                if field.lookup_eq == "*":
972                                    ret += ' else'
973                                    subtree_text = "any %s" %(lookupguide)
974                                elif field.lookup_eq == "skip":
975                                    continue
976                                else:
977                                    ret += '%s (%s == %s)' %(ifblock, lookupguide, field.lookup_eq.upper())
978                                    subtree_text = "%s is %s" %(lookupguide, field.lookup_eq)
979
980                            ret += self.indent_out(' {\n')
981                            self.incr_indent()
982                            if debug:
983                                ret += self.indent_out('/* start union : %s / maxsize: %s */\n' %(self.name, self.maxsize))
984                            currsize = 0
985                            # dissect field
986
987                            ret += self.indent_out('ptvcursor_add_text_with_subtree(cursor, SUBTREE_UNDEFINED_LENGTH, ett_skinny_tree, "%s");\n' %subtree_text)
988                            ret += '%s' %field.dissect()
989                            ret += self.indent_out('ptvcursor_pop_subtree(cursor);\n')
990
991                            currsize += field.intsize
992
993                            # compensate length
994                            if (self.maxsize - currsize) > 0:
995                                ret += self.indent_out('ptvcursor_advance(cursor, %d);\n' %(self.maxsize - currsize))
996
997                            self.decr_indent()
998
999                            # close block
1000                            ret += self.indent_out('}')
1001                            ifblock = ' else if'
1002                        else:
1003                            ret += '/* ERROR %s, missing lookup_guide */' %field.dissect()
1004            ret += '\n'
1005
1006            return ret
1007
1008    class TreeBuilder(xml.sax.handler.ContentHandler):
1009        def __init__(self):
1010            self.stack = []
1011            self.root = DataNode()
1012            self.previous = self.root
1013            self.current = self.root
1014            self.basemessage = None
1015            self.text_parts = []
1016        def startElement(self, name, attrs):
1017            objecttype = {"message": Message(), "fields": Fields(), "enum" : Enum(), "bitfield" : BitField(), "struct": Struct(), "union": Union(), "integer": Integer(), "string": String(), "ether": Ether(), "ip": Ip(), "ipv4or6": Ipv4or6(), "xml": XML(), "code": Code()}
1018            self.previous = self.current
1019            self.stack.append((self.current, self.text_parts))
1020            if name in objecttype.keys():
1021                self.current = objecttype[name]
1022            else:
1023                self.current = DataNode()
1024            if name == "message":
1025                self.basemessage = self.current
1026            self.text_parts = []
1027            #self.children = []
1028            self.current.parent = self.previous
1029            self.current.basemessage = self.basemessage
1030            # xml attributes --> python attributes
1031            for k, v in attrs.items():
1032                self.current._add_xml_attr(_name_mangle(k), v)
1033
1034        def endElement(self, name):
1035            text = ''.join(self.text_parts).strip()
1036            if text:
1037                self.current.data = text
1038            if self.current._attrs:
1039                obj = self.current
1040            else:
1041                # a text only node is simply represented by the string
1042                obj = text or ''
1043            self.current, self.text_parts = self.stack.pop()
1044            self.current._add_xml_attr(_name_mangle(name), obj)
1045            self.current._add_child(_name_mangle(name), obj)
1046        def characters(self, content):
1047            self.text_parts.append(content)
1048
1049    builder = TreeBuilder()
1050    xml.sax.parse(src, builder)
1051    return builder.root._attrs.values()[0]
1052
1053#       skinny = xml2obj('SkinnyProtocolOptimized.xml')
1054#       for message in skinny.message:
1055#         print '%s' %message.dissect()
1056
1057#if __name__ == '__main__':
1058#  import timeit
1059#  print(timeit.timeit("generateMessageDissectors()", setup="from __main__ import generateMessageDissectors"))
1060
1061
1062#skinny = xml2obj('SkinnyProtocolOptimized.xml')
1063#for message in skinny.message:
1064#    print(message)
1065#    message.dissect()
1066
1067#for key,value in fieldsArray.items():
1068#       print "%s : %s" %(key,value)
1069#print '%r\n' %fieldsArray
1070
1071#skinny = xml2obj('SkinnyProtocolOptimized.xml')
1072#for message in skinny.message:
1073#    print message.declaration()
1074