Package Gnumed :: Package pycommon :: Module gmHooks
[frames] | no frames]

Source Code for Module Gnumed.pycommon.gmHooks

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