2
0
mirror of https://gitlab.com/apparmor/apparmor synced 2025-08-29 21:38:15 +00:00

Clean up and document AppArmor UI module

- Add documentation stub for what the UI module is and how JSON works
- Make indentation consistent
- Use pythonic 'if' clauses
- Add two spaces after function definitions (Python style)
This commit is contained in:
Otto Kekäläinen 2019-02-03 20:44:48 +01:00
parent d1634b8fb0
commit eb378f46d5

View File

@ -32,22 +32,36 @@ _ = init_translation()
debug_logger = DebugLogger('UI')
# If Python3, wrap input in raw_input so make check passes
if not 'raw_input' in dir(__builtins__): raw_input = input
if 'raw_input' not in dir(__builtins__):
raw_input = input
ARROWS = {'A': 'UP', 'B': 'DOWN', 'C': 'RIGHT', 'D': 'LEFT'}
UI_mode = 'text'
def write_json(jsonout):
print(json.dumps(jsonout, sort_keys=False, separators=(',', ': ')))
sys.stdout.flush()
print(json.dumps(jsonout, sort_keys=False, separators=(',', ': ')))
sys.stdout.flush()
def set_json_mode():
"""
Currently this is only used by aa-genprof and aa-logprof, while e.g.
aa-status generates its own JSON ourput.
Remember to bump the JSON API version number if the output commands
in this file are modified.
Current known consumers of the JSON output:
- YaST
"""
global UI_mode
UI_mode = 'json'
jsonout = {'dialog': 'apparmor-json-version', 'data': '2.12'}
write_json(jsonout)
# reads the response on command line for json and verifies the response
# for the dialog type
def json_response(dialog_type):
@ -57,6 +71,7 @@ def json_response(dialog_type):
raise AppArmorException('Expected response %s got %s.' % (dialog_type, string))
return rh
def getkey():
key = readkey()
if key == '\x1B':
@ -67,7 +82,9 @@ def getkey():
key = ARROWS[key]
return key.strip()
def UI_Info(text):
"""Facility to output normal text"""
debug_logger.info(text)
if UI_mode == 'json':
jsonout = {'dialog': 'info', 'data': text}
@ -75,7 +92,9 @@ def UI_Info(text):
else: # text mode
sys.stdout.write(text + '\n')
def UI_Important(text):
"""Facility to output important text"""
debug_logger.debug(text)
if UI_mode == 'json':
jsonout = {'dialog': 'important', 'data': text}
@ -83,6 +102,7 @@ def UI_Important(text):
else: # text mode
sys.stdout.write('\n' + text + '\n')
def get_translated_hotkey(translated, cmsg=''):
msg = 'PromptUser: ' + _('Invalid hotkey for')
@ -95,6 +115,7 @@ def get_translated_hotkey(translated, cmsg=''):
else:
raise AppArmorException('%s %s' % (msg, translated))
def UI_YesNo(text, default):
debug_logger.debug('UI_YesNo: %s: %s %s' % (UI_mode, text, default))
default = default.lower()
@ -134,6 +155,7 @@ def UI_YesNo(text, default):
ans = default
return ans
def UI_YesNoCancel(text, default):
debug_logger.debug('UI_YesNoCancel: %s: %s %s' % (UI_mode, text, default))
default = default.lower()
@ -184,6 +206,7 @@ def UI_YesNoCancel(text, default):
ans = default
return ans
def UI_GetString(text, default):
debug_logger.debug('UI_GetString: %s: %s %s' % (UI_mode, text, default))
string = default
@ -201,6 +224,7 @@ def UI_GetString(text, default):
readline.set_startup_hook()
return string.strip()
def UI_GetFile(file):
debug_logger.debug('UI_GetFile: %s' % UI_mode)
filename = None
@ -213,24 +237,29 @@ def UI_GetFile(file):
filename = sys.stdin.read()
return filename
def UI_BusyStart(message):
debug_logger.debug('UI_BusyStart: %s' % UI_mode)
UI_Info(message)
def UI_BusyStop():
debug_logger.debug('UI_BusyStop: %s' % UI_mode)
def diff(oldprofile, newprofile):
difftemp = tempfile.NamedTemporaryFile('w')
subprocess.call('diff -u -p %s %s > %s' % (oldprofile, newprofile, difftemp.name), shell=True)
return difftemp
def write_profile_to_tempfile(profile):
temp = tempfile.NamedTemporaryFile('w')
temp.write(profile)
temp.flush()
return temp
def generate_diff(oldprofile, newprofile):
oldtemp = write_profile_to_tempfile(oldprofile)
newtemp = write_profile_to_tempfile(newprofile)
@ -239,6 +268,7 @@ def generate_diff(oldprofile, newprofile):
newtemp.close()
return difftemp
def generate_diff_with_comments(oldprofile, newprofile):
if not os.path.exists(oldprofile):
raise AppArmorException(_("Can't find existing profile %s to compare changes.") % oldprofile)
@ -247,21 +277,23 @@ def generate_diff_with_comments(oldprofile, newprofile):
newtemp.close()
return difftemp
def UI_Changes(oldprofile, newprofile, comments=False):
if comments == False:
difftemp = generate_diff(oldprofile, newprofile)
header = 'View Changes'
if not comments:
difftemp = generate_diff(oldprofile, newprofile)
header = 'View Changes'
else:
difftemp = generate_diff_with_comments(oldprofile, newprofile)
header = 'View Changes with comments'
difftemp = generate_diff_with_comments(oldprofile, newprofile)
header = 'View Changes with comments'
if UI_mode == 'json':
jsonout = {'dialog': 'changes', 'header':header, 'filename': difftemp.name}
jsonout = {'dialog': 'changes', 'header': header, 'filename': difftemp.name}
write_json(jsonout)
json_response('changes')["response"] # wait for response to delay deletion of difftemp (and ignore response content)
else:
subprocess.call('less %s' % difftemp.name, shell=True)
subprocess.call('less %s' % difftemp.name, shell=True)
difftemp.close()
CMDS = {'CMD_ALLOW': _('(A)llow'),
'CMD_OTHER': _('(M)ore'),
'CMD_AUDIT_NEW': _('Audi(t)'),
@ -324,6 +356,7 @@ CMDS = {'CMD_ALLOW': _('(A)llow'),
'CMD_IGNORE_ENTRY': _('(I)gnore')
}
class PromptQuestion(object):
title = None
headers = None
@ -494,12 +527,14 @@ class PromptQuestion(object):
return ans, selected
def confirm_and_abort():
ans = UI_YesNo(_('Are you sure you want to abandon this set of profile changes and exit?'), 'n')
if ans == 'y':
UI_Info(_('Abandoning all changes.'))
sys.exit(0)
def is_number(number):
try:
return int(number)