root/branch/PacketManipulator/PM/Manager/PreferenceManager.py @ 3933

Revision 3933, 6.9 kB (checked in by nopper, 4 years ago)

Forget to remove qnames

Line 
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3# Copyright (C) 2008 Adriano Monteiro Marques
4#
5# Author: Francesco Piccinno <stack.box@gmail.com>
6#
7# This program is free software; you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by
9# the Free Software Foundation; either version 2 of the License, or
10# (at your option) any later version.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15# GNU General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License
18# along with this program; if not, write to the Free Software
19# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
21"""
22This module contains various class to load and store preferences to
23XML file using SAX parser provided by python
24"""
25
26import os
27import sys
28import os.path
29
30from xml.sax import handler, make_parser
31from xml.sax.saxutils import XMLGenerator
32from xml.sax.xmlreader import AttributesImpl
33
34from PM.Core.Logger import log
35from PM.Core.Const import PM_HOME, PM_PLUGINS_DIR, PLUGINS_DIR
36from PM.Core.Atoms import Singleton
37
38TYPES = {
39    str        : 'str',
40    bool       : 'bool',
41    dict       : 'dict',
42    float      : 'float',
43    int        : 'int',
44    list       : 'list',
45    tuple      : 'tuple'
46}
47
48class Option(object):
49    def __init__(self, value, default=None):
50        self.type = 'str'
51        self.converter = str
52        self.cbs = []
53
54        for k, v in TYPES.items():
55            if isinstance(value, k):
56                self.type = v
57                self.converter = k
58                break
59
60        self._value = self.converter(value)
61
62    def connect(self, callback, call=True):
63        self.cbs.append(callback)
64
65        if call:
66            callback(self.value)
67
68    def disconnect(self, callback):
69        if callback in self.cbs:
70            self.cbs.remove(callback)
71
72    def get_value(self):
73        assert isinstance(self._value, self.converter)
74        return self._value
75
76    def set_value(self, val):
77        # Check type?
78        if not isinstance(val, self.converter):
79            val = self.converter(val)
80
81        for cb in self.cbs:
82            # Lock if a callback returns True
83            if cb(val):
84                log.debug("Ignoring change")
85                return
86
87        log.debug("%s = %s" % (self, val))
88        self._value = val
89
90    def __repr__(self):
91        return "(%s)" % self._value
92
93    value = property(get_value, set_value)
94
95class PreferenceLoader(handler.ContentHandler):
96    def __init__(self, outfile):
97        self.outfile = outfile
98        self.options = {}
99
100    def startElement(self, name, attrs):
101        if name in ('bool', 'int', 'float', \
102                    'str', 'list', 'tuple'):
103
104            opt_name = None
105            opt_value = None
106
107            for attr in attrs.keys():
108                if attr == 'id':
109                    opt_name = attrs.get(attr)
110                if attr == 'value':
111                    opt_value = attrs.get(attr)
112           
113            try:
114                if name == 'bool':
115                    if opt_value.lower() == 'true' or opt_value == '1':
116                        opt_value = True
117                    else:
118                        opt_value = False
119                elif name == 'int':
120                    opt_value = int(opt_value)
121                elif name == 'float':
122                    opt_value = float(opt_value)
123                elif name == 'list':
124                    opt_value = opt_value.split(",")
125                    opt_value = filter(None, opt_value)
126                elif name == 'tuple':
127                    opt_value = opt_value.split(",")
128                    opt_value = filter(None, opt_value)
129                    opt_value = tuple(opt_value)
130            except:
131                return
132
133            if opt_name != None and opt_value != None:
134                self.options[opt_name] = Option(opt_value)
135
136class PreferenceWriter:
137    def startElement(self, names, attrs):
138        self.depth_idx += 1
139        self.writer.characters('  ' * self.depth_idx)
140        self.writer.startElement(names, attrs)
141
142    def endElement(self, name):
143        self.writer.endElement(name)
144        self.writer.characters('\n')
145        self.depth_idx -= 1
146
147    def __init__(self, fname, options):
148        output = open(fname, 'w')
149        self.depth_idx = -1
150        self.writer = XMLGenerator(output, 'utf-8')
151        self.writer.startDocument()
152
153        self.startElement('PacketManipulator', {}),
154        self.writer.characters('\n')
155
156        items = options.items()
157        items.sort()
158
159        for key, option in items:
160
161            attr_vals = {
162                'id' : key,
163                'value' : str(option.value)
164            }
165
166            attrs = AttributesImpl(attr_vals)
167
168            self.startElement(str(option.type), attrs)
169            self.endElement(str(option.type))
170
171        self.endElement('PacketManipulator')
172        self.writer.endDocument()
173        output.close()
174
175class Prefs(Singleton):
176    options = {
177        'gui.docking' : True,
178        'gui.expander.standard' : False,
179        'gui.maintab.sniffview.font' : 'Monospace 10',
180        'gui.maintab.sniffview.usecolors' : True,
181        'gui.maintab.hexview.font' : 'Monospace 10',
182        'gui.maintab.hexview.bpl' : 16,
183        'gui.maintab.sequenceview.font' : 'Monospace 10',
184        'gui.maintab.sequenceview.usecolors' : True,
185        'gui.maintab.autostop' : False,
186        'gui.maintab.askforsave' : True,
187
188        'gui.statustab.font' : 'Monospace 10',
189       
190        'gui.views.protocol_selector_tab' : True,
191        'gui.views.property_tab' : True,
192        'gui.views.status_tab' : True,
193        'gui.views.operations_tab' : True,
194        'gui.views.vte_tab' : False,
195        'gui.views.hack_tab' : False,
196        'gui.views.console_tab' : False,
197
198        'backend.system' : 'scapy',
199        'backend.scapy.interface' : '',
200
201        'plugins.paths' : os.pathsep.join((PM_PLUGINS_DIR, PLUGINS_DIR)),
202        'plugins.enabled' : ''
203    }
204
205    def __init__(self):
206        need_save = True
207        self.fname = os.path.join(PM_HOME, 'pm-prefs.xml')
208       
209        try:
210            opts = self.load_options()
211            self.options.update(self.load_options())
212        except Exception:
213            need_save = True
214
215        diff_dict = {}
216        for name, opt in self.options.items():
217            if not isinstance(opt, Option):
218                diff_dict[name] = Option(opt)
219
220        self.options.update(diff_dict)
221
222        if need_save:
223            self.write_options()
224
225    def load_options(self):
226        handler = PreferenceLoader(sys.stdout)
227        parser = make_parser()
228        parser.setContentHandler(handler)
229        parser.parse(self.fname)
230
231        return handler.options
232
233    def write_options(self):
234        writer = PreferenceWriter(self.fname, self.options)
235
236    def __getitem__(self, x):
237        return self.options[x]
Note: See TracBrowser for help on using the browser.