49
51
if sys.version_info.major == 2:
54
# Show warnings by default
55
if not sys.warnoptions:
56
warnings.simplefilter("default")
58
log = logging.getLogger(os.path.basename(sys.argv[0]))
59
logging.basicConfig(level="NOTSET", # Show all messages
60
format="%(message)s") # Show basic log messages
62
logging.captureWarnings(True) # Show warnings via the logging system
64
locale.setlocale(locale.LC_ALL, "")
66
logging.getLogger("dbus.proxies").setLevel(logging.CRITICAL)
67
logging.getLogger("urwid").setLevel(logging.INFO)
54
locale.setlocale(locale.LC_ALL, '')
56
logging.getLogger('dbus.proxies').setLevel(logging.CRITICAL)
69
58
# Some useful constants
70
domain = "se.recompile"
71
server_interface = domain + ".Mandos"
72
client_interface = domain + ".Mandos.Client"
59
domain = 'se.recompile'
60
server_interface = domain + '.Mandos'
61
client_interface = domain + '.Mandos.Client'
76
65
dbus.OBJECT_MANAGER_IFACE
128
117
self.property_changed_match.remove()
131
class MandosClientWidget(MandosClientPropertyCache, urwid.Widget):
120
class MandosClientWidget(urwid.FlowWidget, MandosClientPropertyCache):
132
121
"""A Mandos Client which is visible on the screen.
135
_sizing = frozenset(["flow"])
137
124
def __init__(self, server_proxy_object=None, update_hook=None,
138
delete_hook=None, **kwargs):
125
delete_hook=None, logger=None, **kwargs):
139
126
# Called on update
140
127
self.update_hook = update_hook
141
128
# Called on delete
142
129
self.delete_hook = delete_hook
143
130
# Mandos Server proxy object
144
131
self.server_proxy_object = server_proxy_object
146
135
self._update_timer_callback_tag = None
183
173
if flag and self._update_timer_callback_tag is None:
184
174
# Will update the shown timer value every second
185
self._update_timer_callback_tag = (
186
GLib.timeout_add(1000,
187
glib_safely(self.update_timer)))
175
self._update_timer_callback_tag = (GLib.timeout_add
188
178
elif not (flag or self._update_timer_callback_tag is None):
189
179
GLib.source_remove(self._update_timer_callback_tag)
190
180
self._update_timer_callback_tag = None
192
182
def checker_completed(self, exitstatus, condition, command):
193
183
if exitstatus == 0:
194
log.debug('Checker for client %s (command "%s")'
195
" succeeded", self.properties["Name"], command)
184
self.logger('Checker for client {} (command "{}")'
185
' succeeded'.format(self.properties["Name"],
199
190
if os.WIFEXITED(condition):
200
log.info('Checker for client %s (command "%s") failed'
201
" with exit code %d", self.properties["Name"],
202
command, os.WEXITSTATUS(condition))
191
self.logger('Checker for client {} (command "{}") failed'
193
.format(self.properties["Name"], command,
194
os.WEXITSTATUS(condition)))
203
195
elif os.WIFSIGNALED(condition):
204
log.info('Checker for client %s (command "%s") was'
205
" killed by signal %d", self.properties["Name"],
206
command, os.WTERMSIG(condition))
196
self.logger('Checker for client {} (command "{}") was'
197
' killed by signal {}'
198
.format(self.properties["Name"], command,
199
os.WTERMSIG(condition)))
209
202
def checker_started(self, command):
210
203
"""Server signals that a checker started."""
211
log.debug('Client %s started checker "%s"',
212
self.properties["Name"], command)
204
self.logger('Client {} started checker "{}"'
205
.format(self.properties["Name"],
214
208
def got_secret(self):
215
log.info("Client %s received its secret",
216
self.properties["Name"])
209
self.logger('Client {} received its secret'
210
.format(self.properties["Name"]))
218
212
def need_approval(self, timeout, default):
220
message = "Client %s needs approval within %f seconds"
214
message = 'Client {} needs approval within {} seconds'
222
message = "Client %s will get its secret in %f seconds"
223
log.info(message, self.properties["Name"], timeout/1000)
216
message = 'Client {} will get its secret in {} seconds'
217
self.logger(message.format(self.properties["Name"],
225
220
def rejected(self, reason):
226
log.info("Client %s was rejected; reason: %s",
227
self.properties["Name"], reason)
221
self.logger('Client {} was rejected; reason: {}'
222
.format(self.properties["Name"], reason))
229
224
def selectable(self):
230
225
"""Make this a "selectable" widget.
231
This overrides the method from urwid.Widget."""
226
This overrides the method from urwid.FlowWidget."""
234
229
def rows(self, maxcolrow, focus=False):
235
230
"""How many rows this widget will occupy might depend on
236
231
whether we have focus or not.
237
This overrides the method from urwid.Widget"""
232
This overrides the method from urwid.FlowWidget"""
238
233
return self.current_widget(focus).rows(maxcolrow, focus=focus)
240
235
def current_widget(self, focus=False):
333
328
def render(self, maxcolrow, focus=False):
334
329
"""Render differently if we have focus.
335
This overrides the method from urwid.Widget"""
330
This overrides the method from urwid.FlowWidget"""
336
331
return self.current_widget(focus).render(maxcolrow,
339
334
def keypress(self, maxcolrow, key):
341
This overrides the method from urwid.Widget"""
336
This overrides the method from urwid.FlowWidget"""
343
338
self.proxy.Set(client_interface, "Enabled",
344
339
dbus.Boolean(True), ignore_reply=True,
471
458
self.log_visible = True
472
459
self.log_wrap = "any"
474
self.loghandler = UILogHandler(self)
477
self.add_log_line(("bold",
478
"Mandos Monitor version " + version))
479
self.add_log_line(("bold", "q: Quit ?: Help"))
462
self.log_message_raw(("bold",
463
"Mandos Monitor version " + version))
464
self.log_message_raw(("bold",
481
self.busname = domain + ".Mandos"
467
self.busname = domain + '.Mandos'
482
468
self.main_loop = GLib.MainLoop()
484
470
def client_not_found(self, key_id, address):
485
log.info("Client with address %s and key ID %s could"
486
" not be found", address, key_id)
471
self.log_message("Client with address {} and key ID {} could"
472
" not be found".format(address, key_id))
488
474
def rebuild(self):
489
475
"""This rebuilds the User Interface.
500
486
self.uilist.append(self.logbox)
501
487
self.topwidget = urwid.Pile(self.uilist)
503
def add_log_line(self, markup):
489
def log_message(self, message, level=1):
490
"""Log message formatted with timestamp"""
491
if level < self.log_level:
493
timestamp = datetime.datetime.now().isoformat()
494
self.log_message_raw("{}: {}".format(timestamp, message),
497
def log_message_raw(self, markup, level=1):
498
"""Add a log message to the log buffer."""
499
if level < self.log_level:
504
501
self.log.append(urwid.Text(markup, wrap=self.log_wrap))
505
502
if self.max_log_length:
506
503
if len(self.log) > self.max_log_length:
507
del self.log[0:(len(self.log) - self.max_log_length)]
504
del self.log[0:len(self.log)-self.max_log_length-1]
508
505
self.logbox.set_focus(len(self.logbox.body.contents)-1,
509
506
coming_from="above")
742
class UILogHandler(logging.Handler):
743
def __init__(self, ui, *args, **kwargs):
745
super(UILogHandler, self).__init__(*args, **kwargs)
747
logging.Formatter("%(asctime)s: %(message)s"))
748
def emit(self, record):
749
msg = self.format(record)
750
if record.levelno > logging.INFO:
752
self.ui.add_log_line(msg)
755
740
ui = UserInterface()
758
743
except KeyboardInterrupt:
759
with warnings.catch_warnings():
760
warnings.filterwarnings("ignore", "", BytesWarning)
763
with warnings.catch_warnings():
764
warnings.filterwarnings("ignore", "", BytesWarning)
745
except Exception as e:
746
ui.log_message(str(e))