def set_dbclient(self, environ, config): logger = cc_logger.dblogger # --------------------------------------------------------------------- # Read from the environment # --------------------------------------------------------------------- self.remote_addr = environ.get("REMOTE_ADDR") self.remote_port = environ.get("REMOTE_PORT") # --------------------------------------------------------------------- # Read from the config file: # --------------------------------------------------------------------- section = CONFIG_FILE_MAIN_SECTION self.ALLOW_MOBILEWEB = get_config_parameter_boolean(config, section, "ALLOW_MOBILEWEB", False) self.DBCLIENT_LOGLEVEL = get_config_parameter_loglevel(config, section, "DBCLIENT_LOGLEVEL", logging.INFO) logger.setLevel(self.DBCLIENT_LOGLEVEL) # --------------------------------------------------------------------- # Read from the database # --------------------------------------------------------------------- self.VALID_TABLE_NAMES = self.db.get_all_table_names()
def __init__(self, *args, **kwargs): """Initialize. Possible methods: RecipientDefinition() RecipientDefinition(config, section) Args: config: ConfigParser INI file object section: name of recipient and of INI file section """ rnc_db.blank_object(self, RecipientDefinition.FIELDS) # HL7 fields not copied to database self.ping_first = None self.network_timeout_ms = None self.idnum_type_list = [None] * NUMBER_OF_IDNUMS self.idnum_aa_list = [None] * NUMBER_OF_IDNUMS self.keep_message = None self.keep_reply = None # File fields not copied to database (because actual filename stored): self.patient_spec_if_anonymous = None self.patient_spec = None self.filename_spec = None self.make_directory = None # Some default values we never want to be None self.include_anonymous = False # Internal use self.valid = False # Variable constructor... nargs = len(args) if nargs == 0: # dummy one self.type = RECIPIENT_TYPE.FILE self.primary_idnum = 1 self.require_idnum_mandatory = False self.finalized_only = False self.task_format = VALUE.OUTPUTTYPE_XML # File self.include_anonymous = True self.patient_spec_if_anonymous = "anonymous" self.patient_spec = "{surname}_{forename}_{idshortdesc1}{idnum1}" self.filename_spec = ( "/tmp/camcops_debug_testing/" "TestCamCOPS_{patient}_{created}_{tasktype}-{serverpk}" ".{filetype}" ) self.overwrite_files = False self.make_directory = True return elif nargs != 2: raise AssertionError("RecipientDefinition: bad __init__ call") # Standard constructor config = args[0] section = args[1] self.recipient = section try: self.type = get_config_parameter( config, section, "TYPE", str, "hl7") self.primary_idnum = get_config_parameter( config, section, "PRIMARY_IDNUM", int, None) self.require_idnum_mandatory = get_config_parameter_boolean( config, section, "REQUIRE_PRIMARY_IDNUM_MANDATORY_IN_POLICY", True) sd = get_config_parameter( config, section, "START_DATE", str, None) self.start_date = cc_dt.get_date_from_string(sd) ed = get_config_parameter( config, section, "END_DATE", str, None) self.end_date = cc_dt.get_date_from_string(ed) self.finalized_only = get_config_parameter_boolean( config, section, "FINALIZED_ONLY", True) self.task_format = get_config_parameter( config, section, "TASK_FORMAT", str, VALUE.OUTPUTTYPE_PDF) self.xml_field_comments = get_config_parameter_boolean( config, section, "XML_FIELD_COMMENTS", True) # HL7 if self.using_hl7(): self.host = get_config_parameter( config, section, "HOST", str, None) self.port = get_config_parameter( config, section, "PORT", int, DEFAULT_HL7_PORT) self.ping_first = get_config_parameter_boolean( config, section, "PING_FIRST", True) self.network_timeout_ms = get_config_parameter( config, section, "NETWORK_TIMEOUT_MS", int, 10000) for n in range(1, NUMBER_OF_IDNUMS + 1): i = n - 1 nstr = str(n) self.idnum_type_list[i] = get_config_parameter( config, section, "IDNUM_TYPE_" + nstr, str, "") self.idnum_aa_list[i] = get_config_parameter( config, section, "IDNUM_AA_" + nstr, str, "") self.keep_message = get_config_parameter_boolean( config, section, "KEEP_MESSAGE", False) self.keep_reply = get_config_parameter_boolean( config, section, "KEEP_REPLY", False) self.divert_to_file = get_config_parameter( config, section, "DIVERT_TO_FILE", str, None) self.treat_diverted_as_sent = get_config_parameter_boolean( config, section, "TREAT_DIVERTED_AS_SENT", False) if self.divert_to_file: self.host = None self.port = None self.ping_first = None self.network_timeout_ms = None self.keep_reply = None self.include_anonymous = False # File if self.using_file(): self.include_anonymous = get_config_parameter_boolean( config, section, "INCLUDE_ANONYMOUS", False) self.patient_spec_if_anonymous = get_config_parameter( config, section, "PATIENT_SPEC_IF_ANONYMOUS", str, "anonymous") self.patient_spec = get_config_parameter( config, section, "PATIENT_SPEC", str, None) self.filename_spec = get_config_parameter( config, section, "FILENAME_SPEC", str, None) self.overwrite_files = get_config_parameter_boolean( config, section, "OVERWRITE_FILES", False) self.make_directory = get_config_parameter_boolean( config, section, "MAKE_DIRECTORY", False) self.rio_metadata = get_config_parameter_boolean( config, section, "RIO_METADATA", False) self.rio_idnum = get_config_parameter( config, section, "RIO_IDNUM", int, None) self.rio_uploading_user = get_config_parameter( config, section, "RIO_UPLOADING_USER", str, None) self.rio_document_type = get_config_parameter( config, section, "RIO_DOCUMENT_TYPE", str, None) self.script_after_file_export = get_config_parameter( config, section, "SCRIPT_AFTER_FILE_EXPORT", str, None) self.check_valid() except ConfigParser.NoSectionError: logger.warning("Config file section missing: [{}]".format( section )) self.valid = False
def set_webview(self, environ, config): # --------------------------------------------------------------------- # Delayed imports # --------------------------------------------------------------------- import cgi import operator import os import urllib import cc_filename import cc_html # caution, circular import import cc_policy import cc_namedtuples import cc_recipdef import cc_version logger = cc_logger.logger # --------------------------------------------------------------------- # Read from the environment # --------------------------------------------------------------------- # http://www.zytrax.com/tech/web/env_var.htm # Apache standard CGI variables: self.SCRIPT_NAME = environ.get("SCRIPT_NAME", "") self.SERVER_NAME = environ.get("SERVER_NAME") # Reconstruct URL: # http://www.python.org/dev/peps/pep-0333/#url-reconstruction url = environ.get("wsgi.url_scheme", "") + "://" if environ.get("HTTP_HOST"): url += environ.get("HTTP_HOST") else: url += environ.get("SERVER_NAME", "") if environ.get("wsgi.url_scheme") == "https": if environ.get("SERVER_PORT") != "443": url += ":" + environ.get("SERVER_PORT", "") else: if environ.get("SERVER_PORT") != "80": url += ":" + environ.get("SERVER_PORT", "") url += urllib.quote(environ.get("SCRIPT_NAME", "")) url += urllib.quote(environ.get("PATH_INFO", "")) # But not the query string: # if environ.get("QUERY_STRING"): # url += "?" + environ.get("QUERY_STRING") self.SCRIPT_PUBLIC_URL_ESCAPED = cgi.escape(url) # --------------------------------------------------------------------- # Read from the config file: # --------------------------------------------------------------------- section = CONFIG_FILE_MAIN_SECTION self.MYSQL = get_config_parameter(config, section, "MYSQL", str, DEFAULT_MYSQL) self.MYSQLDUMP = get_config_parameter(config, section, "MYSQLDUMP", str, DEFAULT_MYSQLDUMP) self.LOCAL_INSTITUTION_URL = get_config_parameter( config, section, "LOCAL_INSTITUTION_URL", str, DEFAULT_LOCAL_INSTITUTION_URL ) # note order dependency: RESOURCES_DIRECTORY, LOCAL_LOGO_FILE_ABSOLUTE self.RESOURCES_DIRECTORY = get_config_parameter( config, section, "RESOURCES_DIRECTORY", str, DEFAULT_RESOURCES_DIRECTORY ) self.LOCAL_LOGO_FILE_ABSOLUTE = get_config_parameter( config, section, "LOCAL_LOGO_FILE_ABSOLUTE", str, os.path.join(self.RESOURCES_DIRECTORY, LOCAL_LOGO_FILE_WEBREF), ) self.INTROSPECTION_DIRECTORY = get_config_parameter( config, section, "INTROSPECTION_DIRECTORY", str, DEFAULT_INTROSPECTION_DIRECTORY ) self.INTROSPECTION = get_config_parameter_boolean(config, section, "INTROSPECTION", True) self.HL7_LOCKFILE = get_config_parameter(config, section, "HL7_LOCKFILE", str, None) self.SUMMARY_TABLES_LOCKFILE = get_config_parameter(config, section, "SUMMARY_TABLES_LOCKFILE", str, None) self.PASSWORD_CHANGE_FREQUENCY_DAYS = get_config_parameter( config, section, "PASSWORD_CHANGE_FREQUENCY_DAYS", int, DEFAULT_PASSWORD_CHANGE_FREQUENCY_DAYS ) self.LOCKOUT_THRESHOLD = get_config_parameter( config, section, "LOCKOUT_THRESHOLD", int, DEFAULT_LOCKOUT_THRESHOLD ) self.LOCKOUT_DURATION_INCREMENT_MINUTES = get_config_parameter( config, section, "LOCKOUT_DURATION_INCREMENT_MINUTES", int, DEFAULT_LOCKOUT_DURATION_INCREMENT_MINUTES ) self.DISABLE_PASSWORD_AUTOCOMPLETE = get_config_parameter_boolean( config, section, "DISABLE_PASSWORD_AUTOCOMPLETE", True ) self.PATIENT_SPEC_IF_ANONYMOUS = get_config_parameter( config, section, "PATIENT_SPEC_IF_ANONYMOUS", str, "anonymous" ) self.PATIENT_SPEC = get_config_parameter(config, section, "PATIENT_SPEC", str, None) self.TASK_FILENAME_SPEC = get_config_parameter(config, section, "TASK_FILENAME_SPEC", str, None) self.TRACKER_FILENAME_SPEC = get_config_parameter(config, section, "TRACKER_FILENAME_SPEC", str, None) self.CTV_FILENAME_SPEC = get_config_parameter(config, section, "CTV_FILENAME_SPEC", str, None) self.WEBVIEW_LOGLEVEL = get_config_parameter_loglevel(config, section, "WEBVIEW_LOGLEVEL", logging.INFO) logger.setLevel(self.WEBVIEW_LOGLEVEL) self.SEND_ANALYTICS = get_config_parameter_boolean(config, section, "SEND_ANALYTICS", True) self.EXPORT_CRIS_DATA_DICTIONARY_TSV_FILE = get_config_parameter( config, section, "EXPORT_CRIS_DATA_DICTIONARY_TSV_FILE", str, None ) # http://stackoverflow.com/questions/335695/lists-in-configparser try: hl7_items = config.items(CONFIG_FILE_RECIPIENTLIST_SECTION) for key, recipientdef_name in hl7_items: logger.debug(u"HL7 config: key={}, recipientdef_name=" "{}".format(key, recipientdef_name)) h = cc_recipdef.RecipientDefinition(config, recipientdef_name) if h.valid: self.HL7_RECIPIENT_DEFS.append(h) except ConfigParser.NoSectionError: logger.info("No config file section [{}]".format(CONFIG_FILE_RECIPIENTLIST_SECTION)) # --------------------------------------------------------------------- # Built from the preceding: # --------------------------------------------------------------------- self.INTROSPECTION_FILES = [] if self.INTROSPECTION: rootdir = self.INTROSPECTION_DIRECTORY for d in INTROSPECTABLE_DIRECTORIES: searchdir = os.sep.join([rootdir, d]) if d else rootdir for fname in os.listdir(searchdir): junk, ext = os.path.splitext(fname) if ext not in INTROSPECTABLE_EXTENSIONS: continue fullpath = os.sep.join([searchdir, fname]) prettypath = os.sep.join([d, fname]) if d else fname self.INTROSPECTION_FILES.append( cc_namedtuples.IntrospectionFileDetails( fullpath=fullpath, prettypath=prettypath, searchterm=fname, ext=ext ) ) self.INTROSPECTION_FILES = sorted(self.INTROSPECTION_FILES, key=operator.attrgetter("prettypath")) # Cache tokenized ID policies cc_policy.tokenize_upload_id_policy(self.ID_POLICY_UPLOAD_STRING) cc_policy.tokenize_finalize_id_policy(self.ID_POLICY_FINALIZE_STRING) # Valid? if not cc_policy.upload_id_policy_valid(): raise RuntimeError("UPLOAD_POLICY invalid in config") if not cc_policy.finalize_id_policy_valid(): raise RuntimeError("FINALIZE_POLICY invalid in config") if self.RESOURCES_DIRECTORY is not None: self.CAMCOPS_STRINGS_FILE_ABSOLUTE = os.path.join(self.RESOURCES_DIRECTORY, CAMCOPS_STRINGS_FILE) self.CAMCOPS_LOGO_FILE_ABSOLUTE = os.path.join(self.RESOURCES_DIRECTORY, CAMCOPS_LOGO_FILE_WEBREF) # Note: HTML4 uses <img ...>; XHTML uses <img ... />; # HTML5 is happy with <img ... /> # IE float-right problems: http://stackoverflow.com/questions/1820007 # Tables are a nightmare in IE (table max-width not working unless you # also specify it for image size, etc.) self.WEB_LOGO = u""" <div class="web_logo_header"> <a href="{}"><img class="logo_left" src="{}" alt="" /></a> <a href="{}"><img class="logo_right" src="{}" alt="" /></a> </div> """.format( self.SCRIPT_NAME, CAMCOPS_LOGO_FILE_WEBREF, self.LOCAL_INSTITUTION_URL, LOCAL_LOGO_FILE_WEBREF ) self.WEBSTART = cc_html.WEB_HEAD + self.WEB_LOGO if cc_version.PDF_ENGINE in ["weasyprint", "pdfkit"]: # weasyprint: div with floating img does not work properly self.PDF_LOGO_LINE = u""" <div class="pdf_logo_header"> <table> <tr> <td class="image_td"> <img class="logo_left" src="file://{}" /> </td> <td class="centregap_td"></td> <td class="image_td"> <img class="logo_right" src="file://{}" /> </td> </tr> </table> </div> """.format( self.CAMCOPS_LOGO_FILE_ABSOLUTE, self.LOCAL_LOGO_FILE_ABSOLUTE ) elif cc_version.PDF_ENGINE in ["pdfkit"]: self.PDF_LOGO_LINE = u""" <div class="pdf_logo_header"> <table> <tr> <td class="image_td"> <img class="logo_left" src="file://{}" /> </td> <td class="centregap_td"></td> <td class="image_td"> <img class="logo_right" src="file://{}" /> </td> </tr> </table> </div> """.format( self.CAMCOPS_LOGO_FILE_ABSOLUTE, self.LOCAL_LOGO_FILE_ABSOLUTE ) # self.PDF_LOGO_LINE = u""" # <div class="pdf_logo_header"> # <img class="logo_left" src="file://{}" /> # <img class="logo_right" src="file://{}" /> # </div> # """.format( # self.CAMCOPS_LOGO_FILE_ABSOLUTE, # self.LOCAL_LOGO_FILE_ABSOLUTE, # ) elif cc_version.PDF_ENGINE in ["xhtml2pdf"]: # xhtml2pdf # hard to get logos positioned any other way than within a table self.PDF_LOGO_LINE = u""" <div class="header"> <table class="noborder"> <tr class="noborder"> <td class="noborderphoto" width="45%"> <img src="file://{}" height="{}" align="left" /> </td> <td class="noborderphoto" width="10%"></td> <td class="noborderphoto" width="45%"> <img src="file://{}" height="{}" align="right" /> </td> </tr> </table> </div> """.format( self.CAMCOPS_LOGO_FILE_ABSOLUTE, cc_html.PDF_LOGO_HEIGHT, self.LOCAL_LOGO_FILE_ABSOLUTE, cc_html.PDF_LOGO_HEIGHT, ) else: raise AssertionError("Invalid PDF engine") if not self.PATIENT_SPEC_IF_ANONYMOUS: raise RuntimeError("Blank PATIENT_SPEC_IF_ANONYMOUS in [server] " "section of config file") if not self.PATIENT_SPEC: raise RuntimeError("Missing/blank PATIENT_SPEC in [server] section" " of config file") if not cc_filename.patient_spec_for_filename_is_valid(self.PATIENT_SPEC): raise RuntimeError("Invalid PATIENT_SPEC in [server] section of " "config file") if not self.TASK_FILENAME_SPEC: raise RuntimeError("Missing/blank TASK_FILENAME_SPEC in " "[server] section of config file") if not cc_filename.filename_spec_is_valid(self.TASK_FILENAME_SPEC): raise RuntimeError("Invalid TASK_FILENAME_SPEC in " "[server] section of config file") if not self.TRACKER_FILENAME_SPEC: raise RuntimeError("Missing/blank TRACKER_FILENAME_SPEC in " "[server] section of config file") if not cc_filename.filename_spec_is_valid(self.TRACKER_FILENAME_SPEC): raise RuntimeError("Invalid TRACKER_FILENAME_SPEC in " "[server] section of config file") if not self.CTV_FILENAME_SPEC: raise RuntimeError("Missing/blank CTV_FILENAME_SPEC in " "[server] section of config file") if not cc_filename.filename_spec_is_valid(self.CTV_FILENAME_SPEC): raise RuntimeError("Invalid CTV_FILENAME_SPEC in " "[server] section of config file")