/mandos/trunk

To get this branch, use:
bzr branch http://bzr.recompile.se/loggerhead/mandos/trunk

« back to all changes in this revision

Viewing changes to mandos-monitor

  • Committer: teddy at bsnet
  • Date: 2011-02-11 18:54:14 UTC
  • mto: This revision was merged to the branch mainline in revision 465.
  • Revision ID: teddy@fukt.bsnet.se-20110211185414-cjmw3hppv9i3h9wh
* mandos-monitor: Use only unicode string literals.
  (MandosClientWidget.rows, MandosClientWidget.render,
  MandosClientWidget.keypress, ConstrainedListBox.keypress) Don't use
                                                            argument
                                                            tuple
                                                            unpacking.

Show diffs side-by-side

added added

removed removed

Lines of Context:
3
3
4
4
# Mandos Monitor - Control and monitor the Mandos server
5
5
6
 
# Copyright © 2009-2011 Teddy Hogeborn
7
 
# Copyright © 2009-2011 Björn Påhlsson
 
6
# Copyright © 2009,2010 Teddy Hogeborn
 
7
# Copyright © 2009,2010 Björn Påhlsson
8
8
9
9
# This program is free software: you can redistribute it and/or modify
10
10
# it under the terms of the GNU General Public License as published by
22
22
# Contact the authors at <mandos@fukt.bsnet.se>.
23
23
24
24
 
25
 
from __future__ import (division, absolute_import, print_function,
26
 
                        unicode_literals)
 
25
from __future__ import division, absolute_import, with_statement
27
26
 
28
27
import sys
29
28
import os
43
42
 
44
43
import locale
45
44
 
46
 
locale.setlocale(locale.LC_ALL, '')
 
45
locale.setlocale(locale.LC_ALL, u'')
47
46
 
48
47
import logging
49
 
logging.getLogger('dbus.proxies').setLevel(logging.CRITICAL)
 
48
logging.getLogger(u'dbus.proxies').setLevel(logging.CRITICAL)
50
49
 
51
50
# Some useful constants
52
 
domain = 'se.bsnet.fukt'
53
 
server_interface = domain + '.Mandos'
54
 
client_interface = domain + '.Mandos.Client'
55
 
version = "1.3.1"
 
51
domain = u'se.bsnet.fukt'
 
52
server_interface = domain + u'.Mandos'
 
53
client_interface = domain + u'.Mandos.Client'
 
54
version = u"1.2.3"
56
55
 
57
56
# Always run in monochrome mode
58
57
urwid.curses_display.curses.has_colors = lambda : False
66
65
    "Parse an ISO 8601 date string to a datetime.datetime()"
67
66
    if not iso:
68
67
        return None
69
 
    d, t = iso.split("T", 1)
70
 
    year, month, day = d.split("-", 2)
71
 
    hour, minute, second = t.split(":", 2)
 
68
    d, t = iso.split(u"T", 1)
 
69
    year, month, day = d.split(u"-", 2)
 
70
    hour, minute, second = t.split(u":", 2)
72
71
    second, fraction = divmod(float(second), 1)
73
72
    return datetime.datetime(int(year),
74
73
                             int(month),
87
86
        self.proxy = proxy_object # Mandos Client proxy object
88
87
        
89
88
        self.properties = dict()
90
 
        self.property_changed_match = (
91
 
            self.proxy.connect_to_signal("PropertyChanged",
92
 
                                         self.property_changed,
93
 
                                         client_interface,
94
 
                                         byte_arrays=True))
 
89
        self.proxy.connect_to_signal(u"PropertyChanged",
 
90
                                     self.property_changed,
 
91
                                     client_interface,
 
92
                                     byte_arrays=True)
95
93
        
96
94
        self.properties.update(
97
95
            self.proxy.GetAll(client_interface,
98
96
                              dbus_interface = dbus.PROPERTIES_IFACE))
99
97
 
100
 
        #XXX This breaks good super behaviour
 
98
        #XXX This break good super behaviour!
101
99
#        super(MandosClientPropertyCache, self).__init__(
102
100
#            *args, **kwargs)
103
101
    
107
105
        """
108
106
        # Update properties dict with new value
109
107
        self.properties[property] = value
110
 
    
111
 
    def delete(self, *args, **kwargs):
112
 
        self.property_changed_match.remove()
113
 
        super(MandosClientPropertyCache, self).__init__(
114
 
            *args, **kwargs)
115
108
 
116
109
 
117
110
class MandosClientWidget(urwid.FlowWidget, MandosClientPropertyCache):
134
127
        self.last_checker_failed = False
135
128
        
136
129
        # The widget shown normally
137
 
        self._text_widget = urwid.Text("")
 
130
        self._text_widget = urwid.Text(u"")
138
131
        # The widget shown when we have focus
139
 
        self._focus_text_widget = urwid.Text("")
 
132
        self._focus_text_widget = urwid.Text(u"")
140
133
        super(MandosClientWidget, self).__init__(
141
134
            update_hook=update_hook, delete_hook=delete_hook,
142
135
            *args, **kwargs)
144
137
        self.opened = False
145
138
        
146
139
        last_checked_ok = isoformat_to_datetime(self.properties
147
 
                                                ["LastCheckedOK"])
 
140
                                                [u"LastCheckedOK"])
148
141
        if last_checked_ok is None:
149
142
            self.last_checker_failed = True
150
143
        else:
153
146
                                        > datetime.timedelta
154
147
                                        (milliseconds=
155
148
                                         self.properties
156
 
                                         ["Interval"]))
 
149
                                         [u"Interval"]))
157
150
        
158
151
        if self.last_checker_failed:
159
152
            self.using_timer(True)
161
154
        if self.need_approval:
162
155
            self.using_timer(True)
163
156
        
164
 
        self.match_objects = (
165
 
            self.proxy.connect_to_signal("CheckerCompleted",
166
 
                                         self.checker_completed,
167
 
                                         client_interface,
168
 
                                         byte_arrays=True),
169
 
            self.proxy.connect_to_signal("CheckerStarted",
170
 
                                         self.checker_started,
171
 
                                         client_interface,
172
 
                                         byte_arrays=True),
173
 
            self.proxy.connect_to_signal("GotSecret",
174
 
                                         self.got_secret,
175
 
                                         client_interface,
176
 
                                         byte_arrays=True),
177
 
            self.proxy.connect_to_signal("NeedApproval",
178
 
                                         self.need_approval,
179
 
                                         client_interface,
180
 
                                         byte_arrays=True),
181
 
            self.proxy.connect_to_signal("Rejected",
182
 
                                         self.rejected,
183
 
                                         client_interface,
184
 
                                         byte_arrays=True))
185
 
        #self.logger('Created client %s' % (self.properties["Name"]))
 
157
        self.proxy.connect_to_signal(u"CheckerCompleted",
 
158
                                     self.checker_completed,
 
159
                                     client_interface,
 
160
                                     byte_arrays=True)
 
161
        self.proxy.connect_to_signal(u"CheckerStarted",
 
162
                                     self.checker_started,
 
163
                                     client_interface,
 
164
                                     byte_arrays=True)
 
165
        self.proxy.connect_to_signal(u"GotSecret",
 
166
                                     self.got_secret,
 
167
                                     client_interface,
 
168
                                     byte_arrays=True)
 
169
        self.proxy.connect_to_signal(u"NeedApproval",
 
170
                                     self.need_approval,
 
171
                                     client_interface,
 
172
                                     byte_arrays=True)
 
173
        self.proxy.connect_to_signal(u"Rejected",
 
174
                                     self.rejected,
 
175
                                     client_interface,
 
176
                                     byte_arrays=True)
186
177
    
187
178
    def property_changed(self, property=None, value=None):
188
179
        super(self, MandosClientWidget).property_changed(property,
189
180
                                                         value)
190
 
        if property == "ApprovalPending":
 
181
        if property == u"ApprovalPending":
191
182
            using_timer(bool(value))
192
183
        
193
184
    def using_timer(self, flag):
212
203
            if self.last_checker_failed:
213
204
                self.last_checker_failed = False
214
205
                self.using_timer(False)
215
 
            #self.logger('Checker for client %s (command "%s")'
216
 
            #            ' was successful'
217
 
            #            % (self.properties["Name"], command))
 
206
            #self.logger(u'Checker for client %s (command "%s")'
 
207
            #            u' was successful'
 
208
            #            % (self.properties[u"Name"], command))
218
209
            self.update()
219
210
            return
220
211
        # Checker failed
222
213
            self.last_checker_failed = True
223
214
            self.using_timer(True)
224
215
        if os.WIFEXITED(condition):
225
 
            self.logger('Checker for client %s (command "%s")'
226
 
                        ' failed with exit code %s'
227
 
                        % (self.properties["Name"], command,
 
216
            self.logger(u'Checker for client %s (command "%s")'
 
217
                        u' failed with exit code %s'
 
218
                        % (self.properties[u"Name"], command,
228
219
                           os.WEXITSTATUS(condition)))
229
220
        elif os.WIFSIGNALED(condition):
230
 
            self.logger('Checker for client %s (command "%s")'
231
 
                        ' was killed by signal %s'
232
 
                        % (self.properties["Name"], command,
 
221
            self.logger(u'Checker for client %s (command "%s")'
 
222
                        u' was killed by signal %s'
 
223
                        % (self.properties[u"Name"], command,
233
224
                           os.WTERMSIG(condition)))
234
225
        elif os.WCOREDUMP(condition):
235
 
            self.logger('Checker for client %s (command "%s")'
236
 
                        ' dumped core'
237
 
                        % (self.properties["Name"], command))
 
226
            self.logger(u'Checker for client %s (command "%s")'
 
227
                        u' dumped core'
 
228
                        % (self.properties[u"Name"], command))
238
229
        else:
239
 
            self.logger('Checker for client %s completed'
240
 
                        ' mysteriously')
 
230
            self.logger(u'Checker for client %s completed'
 
231
                        u' mysteriously')
241
232
        self.update()
242
233
    
243
234
    def checker_started(self, command):
244
 
        #self.logger('Client %s started checker "%s"'
245
 
        #            % (self.properties["Name"], unicode(command)))
 
235
        #self.logger(u'Client %s started checker "%s"'
 
236
        #            % (self.properties[u"Name"], unicode(command)))
246
237
        pass
247
238
    
248
239
    def got_secret(self):
249
240
        self.last_checker_failed = False
250
 
        self.logger('Client %s received its secret'
251
 
                    % self.properties["Name"])
 
241
        self.logger(u'Client %s received its secret'
 
242
                    % self.properties[u"Name"])
252
243
    
253
244
    def need_approval(self, timeout, default):
254
245
        if not default:
255
 
            message = 'Client %s needs approval within %s seconds'
 
246
            message = u'Client %s needs approval within %s seconds'
256
247
        else:
257
 
            message = 'Client %s will get its secret in %s seconds'
 
248
            message = u'Client %s will get its secret in %s seconds'
258
249
        self.logger(message
259
 
                    % (self.properties["Name"], timeout/1000))
 
250
                    % (self.properties[u"Name"], timeout/1000))
260
251
        self.using_timer(True)
261
252
    
262
253
    def rejected(self, reason):
263
 
        self.logger('Client %s was rejected; reason: %s'
264
 
                    % (self.properties["Name"], reason))
 
254
        self.logger(u'Client %s was rejected; reason: %s'
 
255
                    % (self.properties[u"Name"], reason))
265
256
    
266
257
    def selectable(self):
267
258
        """Make this a "selectable" widget.
282
273
    def update(self):
283
274
        "Called when what is visible on the screen should be updated."
284
275
        # How to add standout mode to a style
285
 
        with_standout = { "normal": "standout",
286
 
                          "bold": "bold-standout",
287
 
                          "underline-blink":
288
 
                              "underline-blink-standout",
289
 
                          "bold-underline-blink":
290
 
                              "bold-underline-blink-standout",
 
276
        with_standout = { u"normal": u"standout",
 
277
                          u"bold": u"bold-standout",
 
278
                          u"underline-blink":
 
279
                              u"underline-blink-standout",
 
280
                          u"bold-underline-blink":
 
281
                              u"bold-underline-blink-standout",
291
282
                          }
292
283
 
293
284
        # Rebuild focus and non-focus widgets using current properties
294
285
 
295
286
        # Base part of a client. Name!
296
 
        base = ('%(name)s: '
297
 
                      % {"name": self.properties["Name"]})
298
 
        if not self.properties["Enabled"]:
299
 
            message = "DISABLED"
300
 
        elif self.properties["ApprovalPending"]:
 
287
        base = (u'%(name)s: '
 
288
                      % {u"name": self.properties[u"Name"]})
 
289
        if not self.properties[u"Enabled"]:
 
290
            message = u"DISABLED"
 
291
        elif self.properties[u"ApprovalPending"]:
301
292
            timeout = datetime.timedelta(milliseconds
302
293
                                         = self.properties
303
 
                                         ["ApprovalDelay"])
 
294
                                         [u"ApprovalDelay"])
304
295
            last_approval_request = isoformat_to_datetime(
305
 
                self.properties["LastApprovalRequest"])
 
296
                self.properties[u"LastApprovalRequest"])
306
297
            if last_approval_request is not None:
307
298
                timer = timeout - (datetime.datetime.utcnow()
308
299
                                   - last_approval_request)
309
300
            else:
310
301
                timer = datetime.timedelta()
311
 
            if self.properties["ApprovedByDefault"]:
312
 
                message = "Approval in %s. (d)eny?"
 
302
            if self.properties[u"ApprovedByDefault"]:
 
303
                message = u"Approval in %s. (d)eny?"
313
304
            else:
314
 
                message = "Denial in %s. (a)pprove?"
 
305
                message = u"Denial in %s. (a)pprove?"
315
306
            message = message % unicode(timer).rsplit(".", 1)[0]
316
307
        elif self.last_checker_failed:
317
308
            timeout = datetime.timedelta(milliseconds
318
309
                                         = self.properties
319
 
                                         ["Timeout"])
 
310
                                         [u"Timeout"])
320
311
            last_ok = isoformat_to_datetime(
321
 
                max((self.properties["LastCheckedOK"]
322
 
                     or self.properties["Created"]),
323
 
                    self.properties["LastEnabled"]))
 
312
                max((self.properties[u"LastCheckedOK"]
 
313
                     or self.properties[u"Created"]),
 
314
                    self.properties[u"LastEnabled"]))
324
315
            timer = timeout - (datetime.datetime.utcnow() - last_ok)
325
 
            message = ('A checker has failed! Time until client'
326
 
                       ' gets disabled: %s'
 
316
            message = (u'A checker has failed! Time until client'
 
317
                       u' gets disabled: %s'
327
318
                           % unicode(timer).rsplit(".", 1)[0])
328
319
        else:
329
 
            message = "enabled"
330
 
        self._text = "%s%s" % (base, message)
 
320
            message = u"enabled"
 
321
        self._text = u"%s%s" % (base, message)
331
322
            
332
323
        if not urwid.supports_unicode():
333
 
            self._text = self._text.encode("ascii", "replace")
334
 
        textlist = [("normal", self._text)]
 
324
            self._text = self._text.encode(u"ascii", u"replace")
 
325
        textlist = [(u"normal", self._text)]
335
326
        self._text_widget.set_text(textlist)
336
327
        self._focus_text_widget.set_text([(with_standout[text[0]],
337
328
                                           text[1])
340
331
                                          for text in textlist])
341
332
        self._widget = self._text_widget
342
333
        self._focus_widget = urwid.AttrWrap(self._focus_text_widget,
343
 
                                            "standout")
 
334
                                            u"standout")
344
335
        # Run update hook, if any
345
336
        if self.update_hook is not None:
346
337
            self.update_hook()
350
341
        self.update()
351
342
        return True             # Keep calling this
352
343
    
353
 
    def delete(self, *args, **kwargs):
 
344
    def delete(self):
354
345
        if self._update_timer_callback_tag is not None:
355
346
            gobject.source_remove(self._update_timer_callback_tag)
356
347
            self._update_timer_callback_tag = None
357
 
        for match in self.match_objects:
358
 
            match.remove()
359
 
        self.match_objects = ()
360
348
        if self.delete_hook is not None:
361
349
            self.delete_hook(self)
362
 
        return super(MandosClientWidget, self).delete(*args, **kwargs)
363
350
    
364
351
    def render(self, maxcolrow, focus=False):
365
352
        """Render differently if we have focus.
370
357
    def keypress(self, maxcolrow, key):
371
358
        """Handle keys.
372
359
        This overrides the method from urwid.FlowWidget"""
373
 
        if key == "+":
374
 
            self.proxy.Enable(dbus_interface = client_interface,
375
 
                              ignore_reply=True)
376
 
        elif key == "-":
377
 
            self.proxy.Disable(dbus_interface = client_interface,
378
 
                               ignore_reply=True)
379
 
        elif key == "a":
 
360
        if key == u"+":
 
361
            self.proxy.Enable(dbus_interface = client_interface)
 
362
        elif key == u"-":
 
363
            self.proxy.Disable(dbus_interface = client_interface)
 
364
        elif key == u"a":
380
365
            self.proxy.Approve(dbus.Boolean(True, variant_level=1),
381
 
                               dbus_interface = client_interface,
382
 
                               ignore_reply=True)
383
 
        elif key == "d":
 
366
                               dbus_interface = client_interface)
 
367
        elif key == u"d":
384
368
            self.proxy.Approve(dbus.Boolean(False, variant_level=1),
385
 
                                  dbus_interface = client_interface,
386
 
                               ignore_reply=True)
387
 
        elif key == "R" or key == "_" or key == "ctrl k":
 
369
                                  dbus_interface = client_interface)
 
370
        elif key == u"R" or key == u"_" or key == u"ctrl k":
388
371
            self.server_proxy_object.RemoveClient(self.proxy
389
 
                                                  .object_path,
390
 
                                                  ignore_reply=True)
391
 
        elif key == "s":
392
 
            self.proxy.StartChecker(dbus_interface = client_interface,
393
 
                                    ignore_reply=True)
394
 
        elif key == "S":
395
 
            self.proxy.StopChecker(dbus_interface = client_interface,
396
 
                                   ignore_reply=True)
397
 
        elif key == "C":
398
 
            self.proxy.CheckedOK(dbus_interface = client_interface,
399
 
                                 ignore_reply=True)
 
372
                                                  .object_path)
 
373
        elif key == u"s":
 
374
            self.proxy.StartChecker(dbus_interface = client_interface)
 
375
        elif key == u"S":
 
376
            self.proxy.StopChecker(dbus_interface = client_interface)
 
377
        elif key == u"C":
 
378
            self.proxy.CheckedOK(dbus_interface = client_interface)
400
379
        # xxx
401
 
#         elif key == "p" or key == "=":
 
380
#         elif key == u"p" or key == "=":
402
381
#             self.proxy.pause()
403
 
#         elif key == "u" or key == ":":
 
382
#         elif key == u"u" or key == ":":
404
383
#             self.proxy.unpause()
405
 
#         elif key == "RET":
 
384
#         elif key == u"RET":
406
385
#             self.open()
407
386
        else:
408
387
            return key
426
405
    """
427
406
    def keypress(self, maxcolrow, key):
428
407
        ret = super(ConstrainedListBox, self).keypress(maxcolrow, key)
429
 
        if ret in ("up", "down"):
 
408
        if ret in (u"up", u"down"):
430
409
            return
431
410
        return ret
432
411
 
441
420
        self.screen = urwid.curses_display.Screen()
442
421
        
443
422
        self.screen.register_palette((
444
 
                ("normal",
445
 
                 "default", "default", None),
446
 
                ("bold",
447
 
                 "default", "default", "bold"),
448
 
                ("underline-blink",
449
 
                 "default", "default", "underline"),
450
 
                ("standout",
451
 
                 "default", "default", "standout"),
452
 
                ("bold-underline-blink",
453
 
                 "default", "default", ("bold", "underline")),
454
 
                ("bold-standout",
455
 
                 "default", "default", ("bold", "standout")),
456
 
                ("underline-blink-standout",
457
 
                 "default", "default", ("underline", "standout")),
458
 
                ("bold-underline-blink-standout",
459
 
                 "default", "default", ("bold", "underline",
460
 
                                          "standout")),
 
423
                (u"normal",
 
424
                 u"default", u"default", None),
 
425
                (u"bold",
 
426
                 u"default", u"default", u"bold"),
 
427
                (u"underline-blink",
 
428
                 u"default", u"default", u"underline"),
 
429
                (u"standout",
 
430
                 u"default", u"default", u"standout"),
 
431
                (u"bold-underline-blink",
 
432
                 u"default", u"default", (u"bold", u"underline")),
 
433
                (u"bold-standout",
 
434
                 u"default", u"default", (u"bold", u"standout")),
 
435
                (u"underline-blink-standout",
 
436
                 u"default", u"default", (u"underline", u"standout")),
 
437
                (u"bold-underline-blink-standout",
 
438
                 u"default", u"default", (u"bold", u"underline",
 
439
                                          u"standout")),
461
440
                ))
462
441
        
463
442
        if urwid.supports_unicode():
464
 
            self.divider = "─" # \u2500
465
 
            #self.divider = "━" # \u2501
 
443
            self.divider = u"─" # \u2500
 
444
            #self.divider = u"━" # \u2501
466
445
        else:
467
 
            #self.divider = "-" # \u002d
468
 
            self.divider = "_" # \u005f
 
446
            #self.divider = u"-" # \u002d
 
447
            self.divider = u"_" # \u005f
469
448
        
470
449
        self.screen.start()
471
450
        
485
464
        # This keeps track of whether self.uilist currently has
486
465
        # self.logbox in it or not
487
466
        self.log_visible = True
488
 
        self.log_wrap = "any"
 
467
        self.log_wrap = u"any"
489
468
        
490
469
        self.rebuild()
491
 
        self.log_message_raw(("bold",
492
 
                              "Mandos Monitor version " + version))
493
 
        self.log_message_raw(("bold",
494
 
                              "q: Quit  ?: Help"))
 
470
        self.log_message_raw((u"bold",
 
471
                              u"Mandos Monitor version " + version))
 
472
        self.log_message_raw((u"bold",
 
473
                              u"q: Quit  ?: Help"))
495
474
        
496
475
        self.busname = domain + '.Mandos'
497
476
        self.main_loop = gobject.MainLoop()
498
477
        self.bus = dbus.SystemBus()
499
478
        mandos_dbus_objc = self.bus.get_object(
500
 
            self.busname, "/", follow_name_owner_changes=True)
 
479
            self.busname, u"/", follow_name_owner_changes=True)
501
480
        self.mandos_serv = dbus.Interface(mandos_dbus_objc,
502
481
                                          dbus_interface
503
482
                                          = server_interface)
508
487
            mandos_clients = dbus.Dictionary()
509
488
        
510
489
        (self.mandos_serv
511
 
         .connect_to_signal("ClientRemoved",
 
490
         .connect_to_signal(u"ClientRemoved",
512
491
                            self.find_and_remove_client,
513
492
                            dbus_interface=server_interface,
514
493
                            byte_arrays=True))
515
494
        (self.mandos_serv
516
 
         .connect_to_signal("ClientAdded",
 
495
         .connect_to_signal(u"ClientAdded",
517
496
                            self.add_new_client,
518
497
                            dbus_interface=server_interface,
519
498
                            byte_arrays=True))
520
499
        (self.mandos_serv
521
 
         .connect_to_signal("ClientNotFound",
 
500
         .connect_to_signal(u"ClientNotFound",
522
501
                            self.client_not_found,
523
502
                            dbus_interface=server_interface,
524
503
                            byte_arrays=True))
539
518
                            path=path)
540
519
    
541
520
    def client_not_found(self, fingerprint, address):
542
 
        self.log_message(("Client with address %s and fingerprint %s"
543
 
                          " could not be found" % (address,
 
521
        self.log_message((u"Client with address %s and fingerprint %s"
 
522
                          u" could not be found" % (address,
544
523
                                                    fingerprint)))
545
524
    
546
525
    def rebuild(self):
562
541
    
563
542
    def log_message(self, message):
564
543
        timestamp = datetime.datetime.now().isoformat()
565
 
        self.log_message_raw(timestamp + ": " + message)
 
544
        self.log_message_raw(timestamp + u": " + message)
566
545
    
567
546
    def log_message_raw(self, markup):
568
547
        """Add a log message to the log buffer."""
571
550
            and len(self.log) > self.max_log_length):
572
551
            del self.log[0:len(self.log)-self.max_log_length-1]
573
552
        self.logbox.set_focus(len(self.logbox.body.contents),
574
 
                              coming_from="above")
 
553
                              coming_from=u"above")
575
554
        self.refresh()
576
555
    
577
556
    def toggle_log_display(self):
578
557
        """Toggle visibility of the log buffer."""
579
558
        self.log_visible = not self.log_visible
580
559
        self.rebuild()
581
 
        #self.log_message("Log visibility changed to: "
 
560
        #self.log_message(u"Log visibility changed to: "
582
561
        #                 + unicode(self.log_visible))
583
562
    
584
563
    def change_log_display(self):
585
564
        """Change type of log display.
586
565
        Currently, this toggles wrapping of text lines."""
587
 
        if self.log_wrap == "clip":
588
 
            self.log_wrap = "any"
 
566
        if self.log_wrap == u"clip":
 
567
            self.log_wrap = u"any"
589
568
        else:
590
 
            self.log_wrap = "clip"
 
569
            self.log_wrap = u"clip"
591
570
        for textwidget in self.log:
592
571
            textwidget.set_wrap_mode(self.log_wrap)
593
 
        #self.log_message("Wrap mode: " + self.log_wrap)
 
572
        #self.log_message(u"Wrap mode: " + self.log_wrap)
594
573
    
595
574
    def find_and_remove_client(self, path, name):
596
 
        """Find a client by its object path and remove it.
 
575
        """Find an client from its object path and remove it.
597
576
        
598
577
        This is connected to the ClientRemoved signal from the
599
578
        Mandos server object."""
601
580
            client = self.clients_dict[path]
602
581
        except KeyError:
603
582
            # not found?
604
 
            self.log_message("Unknown client %r (%r) removed", name,
605
 
                             path)
606
583
            return
607
 
        client.delete()
 
584
        self.remove_client(client, path)
608
585
    
609
586
    def add_new_client(self, path):
610
587
        client_proxy_object = self.bus.get_object(self.busname, path)
625
602
        if path is None:
626
603
            path = client.proxy.object_path
627
604
        self.clients_dict[path] = client
628
 
        self.clients.sort(None, lambda c: c.properties["Name"])
 
605
        self.clients.sort(None, lambda c: c.properties[u"Name"])
629
606
        self.refresh()
630
607
    
631
608
    def remove_client(self, client, path=None):
662
639
    
663
640
    def process_input(self, source, condition):
664
641
        keys = self.screen.get_input()
665
 
        translations = { "ctrl n": "down",      # Emacs
666
 
                         "ctrl p": "up",        # Emacs
667
 
                         "ctrl v": "page down", # Emacs
668
 
                         "meta v": "page up",   # Emacs
669
 
                         " ": "page down",      # less
670
 
                         "f": "page down",      # less
671
 
                         "b": "page up",        # less
672
 
                         "j": "down",           # vi
673
 
                         "k": "up",             # vi
 
642
        translations = { u"ctrl n": u"down",      # Emacs
 
643
                         u"ctrl p": u"up",        # Emacs
 
644
                         u"ctrl v": u"page down", # Emacs
 
645
                         u"meta v": u"page up",   # Emacs
 
646
                         u" ": u"page down",      # less
 
647
                         u"f": u"page down",      # less
 
648
                         u"b": u"page up",        # less
 
649
                         u"j": u"down",           # vi
 
650
                         u"k": u"up",             # vi
674
651
                         }
675
652
        for key in keys:
676
653
            try:
678
655
            except KeyError:    # :-)
679
656
                pass
680
657
            
681
 
            if key == "q" or key == "Q":
 
658
            if key == u"q" or key == u"Q":
682
659
                self.stop()
683
660
                break
684
 
            elif key == "window resize":
 
661
            elif key == u"window resize":
685
662
                self.size = self.screen.get_cols_rows()
686
663
                self.refresh()
687
 
            elif key == "\f":  # Ctrl-L
 
664
            elif key == u"\f":  # Ctrl-L
688
665
                self.refresh()
689
 
            elif key == "l" or key == "D":
 
666
            elif key == u"l" or key == u"D":
690
667
                self.toggle_log_display()
691
668
                self.refresh()
692
 
            elif key == "w" or key == "i":
 
669
            elif key == u"w" or key == u"i":
693
670
                self.change_log_display()
694
671
                self.refresh()
695
 
            elif key == "?" or key == "f1" or key == "esc":
 
672
            elif key == u"?" or key == u"f1" or key == u"esc":
696
673
                if not self.log_visible:
697
674
                    self.log_visible = True
698
675
                    self.rebuild()
699
 
                self.log_message_raw(("bold",
700
 
                                      "  ".
701
 
                                      join(("q: Quit",
702
 
                                            "?: Help",
703
 
                                            "l: Log window toggle",
704
 
                                            "TAB: Switch window",
705
 
                                            "w: Wrap (log)"))))
706
 
                self.log_message_raw(("bold",
707
 
                                      "  "
708
 
                                      .join(("Clients:",
709
 
                                             "+: Enable",
710
 
                                             "-: Disable",
711
 
                                             "R: Remove",
712
 
                                             "s: Start new checker",
713
 
                                             "S: Stop checker",
714
 
                                             "C: Checker OK",
715
 
                                             "a: Approve",
716
 
                                             "d: Deny"))))
 
676
                self.log_message_raw((u"bold",
 
677
                                      u"  ".
 
678
                                      join((u"q: Quit",
 
679
                                            u"?: Help",
 
680
                                            u"l: Log window toggle",
 
681
                                            u"TAB: Switch window",
 
682
                                            u"w: Wrap (log)"))))
 
683
                self.log_message_raw((u"bold",
 
684
                                      u"  "
 
685
                                      .join((u"Clients:",
 
686
                                             u"+: Enable",
 
687
                                             u"-: Disable",
 
688
                                             u"R: Remove",
 
689
                                             u"s: Start new checker",
 
690
                                             u"S: Stop checker",
 
691
                                             u"C: Checker OK",
 
692
                                             u"a: Approve",
 
693
                                             u"d: Deny"))))
717
694
                self.refresh()
718
 
            elif key == "tab":
 
695
            elif key == u"tab":
719
696
                if self.topwidget.get_focus() is self.logbox:
720
697
                    self.topwidget.set_focus(0)
721
698
                else:
722
699
                    self.topwidget.set_focus(self.logbox)
723
700
                self.refresh()
724
 
            #elif (key == "end" or key == "meta >" or key == "G"
725
 
            #      or key == ">"):
 
701
            #elif (key == u"end" or key == u"meta >" or key == u"G"
 
702
            #      or key == u">"):
726
703
            #    pass            # xxx end-of-buffer
727
 
            #elif (key == "home" or key == "meta <" or key == "g"
728
 
            #      or key == "<"):
 
704
            #elif (key == u"home" or key == u"meta <" or key == u"g"
 
705
            #      or key == u"<"):
729
706
            #    pass            # xxx beginning-of-buffer
730
 
            #elif key == "ctrl e" or key == "$":
 
707
            #elif key == u"ctrl e" or key == u"$":
731
708
            #    pass            # xxx move-end-of-line
732
 
            #elif key == "ctrl a" or key == "^":
 
709
            #elif key == u"ctrl a" or key == u"^":
733
710
            #    pass            # xxx move-beginning-of-line
734
 
            #elif key == "ctrl b" or key == "meta (" or key == "h":
 
711
            #elif key == u"ctrl b" or key == u"meta (" or key == u"h":
735
712
            #    pass            # xxx left
736
 
            #elif key == "ctrl f" or key == "meta )" or key == "l":
 
713
            #elif key == u"ctrl f" or key == u"meta )" or key == u"l":
737
714
            #    pass            # xxx right
738
 
            #elif key == "a":
 
715
            #elif key == u"a":
739
716
            #    pass            # scroll up log
740
 
            #elif key == "z":
 
717
            #elif key == u"z":
741
718
            #    pass            # scroll down log
742
719
            elif self.topwidget.selectable():
743
720
                self.topwidget.keypress(self.size, key)