Fix build by #if 0 out unused de_sgsap_tmsi() function.
[obnox/wireshark/wip.git] / tools / WiresharkXML.py
1 """
2 Baseclass for reading PDML produced from TShark.
3
4 Copyright (c) 2003 by Gilbert Ramirez <gram@alumni.rice.edu>
5
6 This program is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License
8 as published by the Free Software Foundation; either version 2
9 of the License, or (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19 """
20
21 import sys
22 from xml.sax import saxlib
23 from xml.sax import saxexts
24 from xml.sax import saxutils
25
26 class CaptureFile:
27     pass
28
29 class FoundItException(Exception):
30     pass
31
32 class PacketList:
33     """Holds Packet objects, and has methods for finding
34     items within it."""
35
36     def __init__(self, children=None):
37         if children == None:
38             self.children = []
39         else:
40             self.children = children
41
42     def __getitem__(self, index):
43         """We act like a list."""
44         return self.children[index]
45
46
47     def item_exists(self, name):
48         """Does an item with name 'name' exist in this
49         PacketList?"""
50         for child in self.children:
51             if child.name == name:
52                 return 1
53
54         try:
55             for child in self.children:
56                 child._item_exists(name)
57
58         except FoundItException:
59             return 1
60
61         return 0
62
63     def _item_exists(self, name):
64         for child in self.children:
65             if child.name == name:
66                 raise FoundItException
67             child._item_exists(name)
68
69
70     def get_items(self, name, items=None):
71         """Return all items that match the name 'name'.
72         They are returned in order of a depth-first-search."""
73         if items == None:
74             top_level = 1
75             items = []
76         else:
77             top_level = 0
78
79         for child in self.children:
80             if child.name == name:
81                 items.append(child)
82             child.get_items(name, items)
83
84         if top_level:
85             return PacketList(items)
86
87     def get_items_before(self, name, before_item, items=None):
88         """Return all items that match the name 'name' that
89         exist before the before_item. The before_item is an object.
90         They results are returned in order of a depth-first-search.
91         This function allows you to find fields from protocols that occur
92         before other protocols. For example, if you have an HTTP
93         protocol, you can find all tcp.dstport fields *before* that HTTP
94         protocol. This helps analyze in the presence of tunneled protocols."""
95         if items == None:
96             top_level = 1
97             items = []
98         else:
99             top_level = 0
100
101         for child in self.children:
102             if top_level == 1 and child == before_item:
103                 break
104             if child.name == name:
105                 items.append(child)
106             # Call get_items because the 'before_item' applies
107             # only to the top level search.
108             child.get_items(name, items)
109
110         if top_level:
111             return PacketList(items)
112
113
114 class ProtoTreeItem(PacketList):
115     def __init__(self, xmlattrs):
116         PacketList.__init__(self)
117
118         self.name = xmlattrs.get("name", "")
119         self.showname = xmlattrs.get("showname", "")
120         self.pos = xmlattrs.get("pos", "")
121         self.size = xmlattrs.get("size", "")
122         self.value = xmlattrs.get("value", "")
123         self.show = xmlattrs.get("show", "")
124         self.hide = xmlattrs.get("hide", "")
125
126     def add_child(self, child):
127         self.children.append(child)
128
129     def get_name(self):
130         return self.name
131
132     def get_showname(self):
133         return self.showname
134
135     def get_pos(self):
136         return self.pos
137
138     def get_size(self):
139         return self.size
140
141     def get_value(self):
142         return self.value
143
144     def get_show(self):
145         return self.show
146
147     def get_hide(self):
148         return self.hide
149
150     def dump(self, fh):
151         if self.name:
152             print >> fh, " name=%s" % (saxutils.quoteattr(self.name),),
153
154         if self.showname:
155             print >> fh, "showname=%s" % (saxutils.quoteattr(self.showname),),
156
157         if self.pos:
158             print >> fh, "pos=%s" % (saxutils.quoteattr(self.pos),),
159
160         if self.size:
161             print >> fh, "size=%s" % (saxutils.quoteattr(self.size),),
162
163         if self.value:
164             print >> fh, "value=%s" % (saxutils.quoteattr(self.value),),
165
166         if self.show:
167             print >> fh, "show=%s" % (saxutils.quoteattr(self.show),),
168
169         if self.hide:
170             print >> fh, "hide=%s" % (saxutils.quoteattr(self.hide),),
171
172 class Packet(ProtoTreeItem, PacketList):
173     def dump(self, fh, indent=0):
174         print >> fh, "  " * indent, "<packet>"
175         indent += 1
176         for child in self.children:
177             child.dump(fh, indent)
178         print >> fh, "  " * indent, "</packet>"
179
180
181 class Protocol(ProtoTreeItem):
182
183     def dump(self, fh, indent=0):
184         print >> fh, "%s<proto " %  ("  " * indent,),
185        
186         ProtoTreeItem.dump(self, fh)
187
188         print >> fh, '>'
189
190         indent += 1
191         for child in self.children:
192             child.dump(fh, indent)
193         print >> fh, "  " * indent, "</proto>"
194
195
196 class Field(ProtoTreeItem):
197
198     def dump(self, fh, indent=0):
199         print >> fh, "%s<field " % ("  " * indent,),
200
201         ProtoTreeItem.dump(self, fh)
202
203         if self.label:
204             print >> fh, "label=%s" % (saxutils.quoteattr(self.label),),
205
206         if self.children:
207             print >> fh, ">"
208             indent += 1
209             for child in self.children:
210                 child.dump(fh, indent)
211             print >> fh, "  " * indent, "</field>"
212
213         else:
214             print >> fh, "/>"
215
216
217 class ParseXML(saxlib.HandlerBase):
218
219     ELEMENT_FILE        = "pdml"
220     ELEMENT_FRAME       = "packet"
221     ELEMENT_PROTOCOL    = "proto"
222     ELEMENT_FIELD       = "field"
223
224     def __init__(self, cb):
225         self.cb = cb
226         self.chars = ""
227         self.element_stack = []
228
229     def startElement(self, name, xmlattrs):
230         self.chars = ""
231
232         if name == self.ELEMENT_FILE:
233             # Eventually, we should check version number of pdml here
234             elem = CaptureFile()
235
236         elif name == self.ELEMENT_FRAME:
237             elem = Packet(xmlattrs)
238
239         elif name == self.ELEMENT_PROTOCOL:
240             elem = Protocol(xmlattrs)
241
242         elif name == self.ELEMENT_FIELD:
243             elem = Field(xmlattrs)
244
245         else:
246             sys.exit("Unknown element: %s" % (name,))
247
248         self.element_stack.append(elem)
249
250
251     def endElement(self, name):
252         elem = self.element_stack.pop()
253
254 #        if isinstance(elem, Field):
255 #            if elem.get_name() == "frame.number":
256 #                print >> sys.stderr, "Packet:", elem.get_show()
257
258         # Add element as child to previous element as long
259         # as there is more than 1 element in the stack. Only
260         # one element in the stack means that the the element in
261         # the stack is the single CaptureFile element, and we don't
262         # want to add this element to that, as we only want one
263         # Packet element in memory at a time.
264         if len(self.element_stack) > 1:
265             parent_elem = self.element_stack[-1]
266             parent_elem.add_child(elem)
267         
268         self.chars = ""
269
270         # If we just finished a Packet element, hand it to the
271         # user's callback.
272         if isinstance(elem, Packet):
273             self.cb(elem)
274
275     def characters(self, chars, start, length):
276         self.chars = self.chars + chars[start:start+length]
277
278
279 def parse_fh(fh, cb):
280
281     # Create a parser
282     parser = saxexts.make_parser()
283
284     # Create the handler
285     ch = ParseXML(cb)
286
287     # Tell the parser to use our handler
288     parser.setDocumentHandler(ch)
289
290     # Parse the file
291     parser.parseFile(fh)
292
293     # Close the parser
294     parser.close()
295
296 def _test():
297     import sys
298
299     def test_cb(obj):
300         pass
301
302     filename = sys.argv[1]
303     fh = open(filename, "r")
304     parse_fh(fh, test_cb)
305
306 if __name__ == '__main__':
307     _test()