예제 #1
0
	def _drop_target_consume_filenames(self, filenames):
		# act on first file only
		fname = filenames[0]
		_log.debug('importing SQL from <%s>', fname)
		# act on text files only
		mime_type = gmMimeLib.guess_mimetype(fname)
		_log.debug('mime type: %s', mime_type)
		if not mime_type.startswith('text/'):
			_log.debug('not a text file')
			gmDispatcher.send(signal='statustext', msg = _('Cannot read SQL from [%s]. Not a text file.') % fname, beep = True)
			return False
#		# act on "small" files only
#		stat_val = os.stat(fname)
#		if stat_val.st_size > 5000:
#			gmDispatcher.send(signal='statustext', msg = _('Cannot read SQL from [%s]. File too big (> 2000 bytes).') % fname, beep = True)
#			return False
		# all checks passed
		for line in fileinput.input(fname):
			self._TCTRL_query.AppendText(line)
예제 #2
0
	def add_filenames(self, filenames):
		# act on first file only
		fname = filenames[0]
		_log.debug('importing SQL from <%s>', fname)
		# act on text files only
		mime_type = gmMimeLib.guess_mimetype(fname)
		_log.debug('mime type: %s', mime_type)
		if not mime_type.startswith('text/'):
			_log.debug('not a text file')
			gmDispatcher.send(signal='statustext', msg = _('Cannot read SQL from [%s]. Not a text file.') % fname, beep = True)
			return False
#		# act on "small" files only
#		stat_val = os.stat(fname)
#		if stat_val.st_size > 5000:
#			gmDispatcher.send(signal='statustext', msg = _('Cannot read SQL from [%s]. File too big (> 2000 bytes).') % fname, beep = True)
#			return False
		# all checks passed
		for line in fileinput.input(fname):
			self._TCTRL_query.AppendText(line)
예제 #3
0
def is_encrypted_pdf(filename: str = None, verbose: bool = False) -> bool:
    """Check encryption status of PDF.

	Requires qpdf to be installed.

	Returns:
		True/False/None: None -- unknown or not PDF
	"""
    assert (filename is not None), '<filename> must not be None'

    mimetype = gmMimeLib.guess_mimetype(filename=filename)
    if mimetype != 'application/pdf':
        _log.info('not a PDF')
        return None

    _log.debug('checking PDF encryption')
    for cmd in ['qpdf', 'qpdf.exe']:
        found, binary = gmShellAPI.detect_external_binary(binary=cmd)
        if found:
            break
    if not found:
        _log.warning('no qpdf binary found')
        return None

    args = [binary, '--verbose', '--is-encrypted', '--', filename]
    success, exit_code, stdout = gmShellAPI.run_process(
        cmd_line=args,
        encoding='utf8',
        verbose=verbose,
        acceptable_return_codes=[0, 2])
    if not success:
        return None

    if exit_code == 0:
        return True

    if exit_code == 2:
        return False

    return None
예제 #4
0
def check_mimetypes_in_archive():
	mimetypes = {}
	cmd = 'SELECT pk FROM blobs.doc_med'
	doc_pks, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd}])
	print('Detecting mimetypes in document archive ...')
	doc_idx = 0
	part_count = 0
	for pk_row in doc_pks:
		doc_idx += 1
		print('\n#%s - document %s of %s: ' % (pk_row['pk'], doc_idx, len(doc_pks)), end = '')
		doc = cDocument(aPK_obj = pk_row['pk'])
		for part in doc.parts:
			part_count += 1
			print('#%s:%s bytes, ' % (part['pk_obj'], part['size']), end = '')
			part_fname = part.save_to_file()
			mimetype = gmMimeLib.guess_mimetype(part_fname)
			try:
				mimetypes[mimetype]['count'] += 1
			except KeyError:
				mimetypes[mimetype] = {
					'count': 1,
					'viewer': gmMimeLib.get_viewer_cmd(mimetype),
					'editor': gmMimeLib.get_editor_cmd(mimetype),
					'extension': gmMimeLib.guess_ext_by_mimetype(mimetype)
				}
	print('')
	print('')
	print('Number of documents :', len(doc_pks))
	print('Number of parts     :', part_count)
	print('Number of mime types:', len(mimetypes))
	for mimetype in mimetypes:
		print('')
		print('<%s>' % mimetype)
		print(' Extension:', mimetypes[mimetype]['extension'])
		print(' Use count:', mimetypes[mimetype]['count'])
		print('    Viewer:', mimetypes[mimetype]['viewer'])
		print('    Editor:', mimetypes[mimetype]['editor'])
	return 0
예제 #5
0
def compose_email(sender=None,
                  receiver=None,
                  message=None,
                  subject=None,
                  files2attach=None):
    # filenames unicode
    # file content binary or utf8
    # files2attach = [(filename, mimetype-or-None), ...]

    if message is None:
        raise ValueError('<message> is None, cannot compose email')

    message = message.lstrip().lstrip('\r\n').lstrip()

    if sender is None:
        sender = default_mail_sender

    if receiver is None:
        receiver = [default_mail_receiver]

    if subject is None:
        subject = 'compose_email() test'

    if files2attach is None:
        email = MIMEText(message, 'plain', 'utf8')
    else:
        email = MIMEMultipart()
        email.attach(MIMEText(message, 'plain', 'utf8'))

    email['From'] = sender
    email['To'] = ', '.join(receiver)
    email['Subject'] = subject

    if files2attach is None:
        return email

    for file2attach in files2attach:
        filename = file2attach[0]
        try:
            mimetype = file2attach[1]
        except IndexError:
            mimetype = gmMimeLib.guess_mimetype(filename=filename)
        # text/*
        if mimetype.startswith('text/'):
            txt = io.open(filename, mode='rt', encoding='utf8')
            attachment = MIMEText(txt.read(), 'plain', 'utf8')
            txt.close()
        # image/*
        elif mimetype.startswith('image/'):
            img = io.open(filename, mode='rb')
            attachment = MIMEImage(img.read())
            img.close()
        # audio/*
        elif mimetype.startswith('audio/'):
            song = io.open(filename, mode='rb')
            attachment = MIMEAudio(song.read())
            song.close()
        # catch-all application/*
        else:
            _log.debug('attaching [%s] with type [%s]', filename, mimetype)
            mime_subtype = mimetype.split('/', 1)[1]
            data = io.open(filename, mode='rb')
            attachment = MIMEApplication(data.read(), mime_subtype)
            data.close()

        try:
            attachment.replace_header(
                'Content-Disposition', 'attachment; filename="%s"' %
                gmTools.fname_from_path(filename))
        except KeyError:
            attachment.add_header(
                'Content-Disposition', 'attachment; filename="%s"' %
                gmTools.fname_from_path(filename))
        email.attach(attachment)

    return email
예제 #6
0
def edit_visual_progress_note(filename=None,
                              episode=None,
                              discard_unmodified=False,
                              doc_part=None,
                              health_issue=None):
    """This assumes <filename> contains an image which can be handled by the configured image editor."""

    if doc_part is not None:
        filename = doc_part.save_to_file()
        if filename is None:
            gmDispatcher.send(
                signal='statustext',
                msg=_('Cannot export visual progress note to file.'))
            return None

    editor = gmCfgDB.get4user(
        option='external.tools.visual_soap_editor_cmd',
        workplace=gmPraxis.gmCurrentPraxisBranch().active_workplace)

    if editor is None:
        _log.error(
            'no editor for visual progress notes configured, trying mimetype editor'
        )
        gmDispatcher.send(
            signal='statustext',
            msg=_('Editor for visual progress note not configured.'),
            beep=False)
        mimetype = gmMimeLib.guess_mimetype(filename=filename)
        editor = gmMimeLib.get_editor_cmd(mimetype=mimetype, filename=filename)
        if editor is None:
            _log.error(
                'no editor for mimetype <%s> configured, trying mimetype viewer',
                mimetype)
            success, msg = gmMimeLib.call_viewer_on_file(aFile=filename,
                                                         block=True)
            if not success:
                _log.debug('problem running mimetype <%s> viewer', mimetype)
                gmGuiHelpers.gm_show_error(
                    _('There is no editor for visual progress notes defined.\n'
                      'Also, there is no editor command defined for the file type\n'
                      '\n'
                      ' [%s].\n'
                      '\n'
                      'Therefor GNUmed attempted to at least *show* this\n'
                      'visual progress note. That failed as well, however:\n'
                      '\n'
                      '%s') % (mimetype, msg),
                    _('Editing visual progress note'))
                editor = configure_visual_progress_note_editor()
                if editor is None:
                    gmDispatcher.send(
                        signal='statustext',
                        msg=_(
                            'Editor for visual progress note not configured.'),
                        beep=True)
                    return None

    if '%(img)s' in editor:
        editor = editor % {'img': filename}
    else:
        editor = '%s %s' % (editor, filename)

    if discard_unmodified:
        original_stat = os.stat(filename)
        original_md5 = gmTools.file2md5(filename)

    success = gmShellAPI.run_command_in_shell(editor, blocking=True)
    if not success:
        success, msg = gmMimeLib.call_viewer_on_file(aFile=filename,
                                                     block=True)
        if not success:
            _log.debug('problem running mimetype <%s> viewer', mimetype)
            gmGuiHelpers.gm_show_error(
                _('There was a problem running the editor\n'
                  '\n'
                  ' [%s] (%s)\n'
                  '\n'
                  'on the visual progress note.\n'
                  '\n'
                  'Therefor GNUmed attempted to at least *show* it.\n'
                  'That failed as well, however:\n'
                  '\n'
                  '%s') % (editor, mimetype, msg),
                _('Editing visual progress note'))
            editor = configure_visual_progress_note_editor()
            if editor is None:
                gmDispatcher.send(
                    signal='statustext',
                    msg=_('Editor for visual progress note not configured.'),
                    beep=True)
        return None

    try:
        open(filename, 'r').close()
    except Exception:
        _log.exception('problem accessing visual progress note file [%s]',
                       filename)
        gmGuiHelpers.gm_show_error(
            _('There was a problem reading the visual\n'
              'progress note from the file:\n'
              '\n'
              ' [%s]\n'
              '\n') % filename, _('Saving visual progress note'))
        return None

    if discard_unmodified:
        modified_stat = os.stat(filename)
        # same size ?
        if original_stat.st_size == modified_stat.st_size:
            modified_md5 = gmTools.file2md5(filename)
            # same hash ?
            if original_md5 == modified_md5:
                _log.debug('visual progress note (template) not modified')
                # ask user to decide
                msg = _(
                    'You either created a visual progress note from a template\n'
                    'in the database (rather than from a file on disk) or you\n'
                    'edited an existing visual progress note.\n'
                    '\n'
                    'The template/original was not modified at all, however.\n'
                    '\n'
                    'Do you still want to save the unmodified image as a\n'
                    'visual progress note into the EMR of the patient ?\n')
                save_unmodified = gmGuiHelpers.gm_show_question(
                    msg, _('Saving visual progress note'))
                if not save_unmodified:
                    _log.debug('user discarded unmodified note')
                    return

    if doc_part is not None:
        _log.debug('updating visual progress note')
        doc_part.update_data_from_file(fname=filename)
        doc_part.set_reviewed(technically_abnormal=False,
                              clinically_relevant=True)
        return None

    if not isinstance(episode, gmEMRStructItems.cEpisode):
        if episode is None:
            episode = _('visual progress notes')
        pat = gmPerson.gmCurrentPatient()
        emr = pat.emr
        episode = emr.add_episode(episode_name=episode.strip(),
                                  pk_health_issue=health_issue,
                                  is_open=False)

    doc = gmDocumentWidgets.save_file_as_new_document(
        filename=filename,
        document_type=gmDocuments.DOCUMENT_TYPE_VISUAL_PROGRESS_NOTE,
        episode=episode,
        unlock_patient=False,
        pk_org_unit=gmPraxis.gmCurrentPraxisBranch()['pk_org_unit'],
        date_generated=gmDateTime.pydt_now_here())
    doc.set_reviewed(technically_abnormal=False, clinically_relevant=True)

    return doc
예제 #7
0
def compose_email(sender=None, receiver=None, message=None, subject=None, files2attach=None):
	# filenames unicode
	# file content binary or utf8
	# files2attach = [(filename, mimetype-or-None), ...]

	if message is None:
		raise ValueError('<message> is None, cannot compose email')

	message = message.lstrip().lstrip('\r\n').lstrip()

	if sender is None:
		sender = default_mail_sender

	if receiver is None:
		receiver = [default_mail_receiver]

	if subject is None:
		subject = 'compose_email() test'

	if files2attach is None:
		email = MIMEText(message, 'plain', 'utf8')
	else:
		email = MIMEMultipart()
		email.attach(MIMEText(message, 'plain', 'utf8'))

	email['From'] = sender
	email['To'] = ', '.join(receiver)
	email['Subject'] = subject

	if files2attach is None:
		return email

	for file2attach in files2attach:
		filename = file2attach[0]
		try:
			mimetype = file2attach[1]
		except IndexError:
			mimetype = gmMimeLib.guess_mimetype(filename = filename)
		# text/*
		if mimetype.startswith('text/'):
			txt = io.open(filename, mode = 'rt', encoding = 'utf8')
			attachment = MIMEText(txt.read(), 'plain', 'utf8')
			txt.close()
		# image/*
		elif mimetype.startswith('image/'):
			img = io.open(filename, mode = 'rb')
			attachment = MIMEImage(img.read())
			img.close()
		# audio/*
		elif mimetype.startswith('audio/'):
			song = io.open(filename, mode = 'rb')
			attachment = MIMEAudio(song.read())
			song.close()
		# catch-all application/*
		else:
			_log.debug('attaching [%s] with type [%s]', filename, mimetype)
			mime_subtype = mimetype.split('/', 1)[1]
			data = io.open(filename, mode = 'rb')
			attachment = MIMEApplication(data.read(), mime_subtype)
			data.close()

		try:
			attachment.replace_header('Content-Disposition', 'attachment; filename="%s"' % gmTools.fname_from_path(filename))
		except KeyError:
			attachment.add_header('Content-Disposition', 'attachment; filename="%s"' % gmTools.fname_from_path(filename))
		email.attach(attachment)

	return email