/var/lib/gnumed/server/pycommon/gmHooks.py is in gnumed-server 16.17-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 | """GNUmed hooks framework.
This module provides convenience functions and definitions
for accessing the GNUmed hooks framework.
This framework calls the script
~/.gnumed/scripts/hook_script.py
at various times during client execution. The script must
contain a function
def run_script(hook=None):
pass
which accepts a single argument <hook>. That argument will
contain the hook that is being activated.
"""
# ========================================================================
__version__ = "$Revision: 1.18 $"
__author__ = "K. Hilbert <Karsten.Hilbert@gmx.net>"
__license__ = "GPL v2 or later (details at http://www.gnu.org)"
# stdlib
import os, sys, stat, logging
_log = logging.getLogger('gm.hook')
_log.info(__version__)
# GNUmed libs
if __name__ == '__main__':
sys.path.insert(0, '../../')
from Gnumed.pycommon import gmDispatcher, gmTools
# ========================================================================
known_hooks = [
u'post_patient_activation',
u'post_person_creation',
u'shutdown-post-GUI',
u'startup-after-GUI-init',
u'startup-before-GUI',
u'request_user_attention',
u'app_activated_startup',
u'app_activated',
u'app_deactivated',
u'after_substance_intake_modified',
u'after_test_result_modified',
u'after_soap_modified',
u'after_code_link_modified',
u'after_new_doc_created',
u'before_print_doc',
u'before_fax_doc',
u'before_mail_doc',
u'before_print_doc_part',
u'before_fax_doc_part',
u'before_mail_doc_part',
u'before_external_doc_access',
u'db_maintenance_warning'
]
_log.debug('known hooks:')
for hook in known_hooks:
_log.debug(hook)
# ========================================================================
hook_module = None
def import_hook_module(reimport=False):
global hook_module
if not reimport:
if hook_module is not None:
return True
# hardcoding path and script name allows us to
# not need configuration for it, the environment
# can always be detected at runtime (workplace etc)
script_name = 'hook_script.py'
script_path = os.path.expanduser(os.path.join('~', '.gnumed', 'scripts'))
full_script = os.path.join(script_path, script_name)
if not os.access(full_script, os.F_OK):
_log.warning('creating default hook script')
f = open(full_script, 'w')
f.write("""
# known hooks:
# %s
def run_script(hook=None):
pass
""" % '# '.join(known_hooks))
f.close()
os.chmod(full_script, 384)
if os.path.islink(full_script):
gmDispatcher.send (
signal = 'statustext',
msg = _('Script must not be a link: [%s].') % full_script
)
return False
if not os.access(full_script, os.R_OK):
gmDispatcher.send (
signal = 'statustext',
msg = _('Script must be readable by the calling user: [%s].') % full_script
)
return False
script_stat_val = os.stat(full_script)
_log.debug('hook script stat(): %s', script_stat_val)
script_perms = stat.S_IMODE(script_stat_val.st_mode)
_log.debug('hook script mode: %s (oktal: %s)', script_perms, oct(script_perms))
if script_perms != 384: # octal 0600
if os.name in ['nt']:
_log.warning('this platform does not support os.stat() file permission checking')
else:
gmDispatcher.send (
signal = 'statustext',
msg = _('Script must be readable by the calling user only (permissions "0600"): [%s].') % full_script
)
return False
try:
tmp = gmTools.import_module_from_directory(script_path, script_name)
except StandardError:
_log.exception('cannot import hook script')
return False
hook_module = tmp
# if reimport:
# reload(tmp) # this has well-known shortcomings !
_log.info('hook script: %s', full_script)
return True
# ========================================================================
def run_hook_script(hook=None):
# NOTE: this just *might* be a huge security hole
if hook not in known_hooks:
raise ValueError('run_hook_script(): unknown hook [%s]' % hook)
if not import_hook_module(reimport = False):
return False
try:
hook_module.run_script(hook = hook)
except StandardError:
_log.exception('error running hook script for [%s]', hook)
gmDispatcher.send (
signal = u'statustext',
msg = _('Error running hook [%s] script.') % hook,
beep = True
)
return False
return True
# ========================================================================
if __name__ == '__main__':
run_hook_script(hook = 'shutdown-post-GUI')
run_hook_script(hook = 'invalid hook')
# ========================================================================
|