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