mirror of
https://gitlab.com/apparmor/apparmor
synced 2025-08-30 13:58:22 +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:
parent
d1634b8fb0
commit
eb378f46d5
@ -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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user