def _kpm_file_path_is_valid(file_path): if not file_path: return False if not os.path.isfile(file_path) and os.access(file_path, os.R_OK): return False if not archive.is_archive(file_path): return False return True
def message_data_from_kpm(target_file, dest_dir, encoding='utf-8'): """ Retrieve the stored details describing a message from a previously exported file. :param str target_file: The file to load as a message archive. :param str dest_dir: The directory to extract data and attachment files to. :param str encoding: The encoding to use for strings. :return: The restored details from the message config. :rtype: dict """ if not archive.is_archive(target_file): logger.warning('the file is not recognized as a valid archive') raise errors.KingPhisherInputValidationError('file is not in the correct format') kpm = archive.ArchiveFile(target_file, 'r') attachment_member_names = [n for n in kpm.file_names if n.startswith('attachments' + os.path.sep)] attachments = [] if not kpm.has_file('message_config.json'): logger.warning('the kpm archive is missing the message_config.json file') raise errors.KingPhisherInputValidationError('data is missing from the message archive') message_config = kpm.get_json('message_config.json') message_config.pop('company_name', None) if attachment_member_names: attachment_dir = os.path.join(dest_dir, 'attachments') if not os.path.isdir(attachment_dir): os.mkdir(attachment_dir) for file_name in attachment_member_names: arcfile_h = kpm.get_file(file_name) file_path = os.path.join(attachment_dir, os.path.basename(file_name)) with open(file_path, 'wb') as file_h: shutil.copyfileobj(arcfile_h, file_h) attachments.append(file_path) logger.debug("extracted {0} attachment file{1} from the archive".format(len(attachments), 's' if len(attachments) > 1 else '')) for config_name, file_name in KPM_ARCHIVE_FILES.items(): if not file_name in kpm.file_names: if config_name in message_config: logger.warning("the kpm archive is missing the {0} file".format(file_name)) raise errors.KingPhisherInputValidationError('data is missing from the message archive') continue if not message_config.get(config_name): logger.warning("the kpm message configuration is missing the {0} setting".format(config_name)) raise errors.KingPhisherInputValidationError('data is missing from the message archive') arcfile_h = kpm.get_file(file_name) file_path = os.path.join(dest_dir, os.path.basename(message_config[config_name])) with open(file_path, 'wb') as file_h: shutil.copyfileobj(arcfile_h, file_h) message_config[config_name] = file_path if 'message_content.html' in kpm.file_names: if 'html_file' not in message_config: logger.warning('the kpm message configuration is missing the html_file setting') raise errors.KingPhisherInputValidationError('data is missing from the message archive') arcfile_h = kpm.get_file('message_content.html') file_path = os.path.join(dest_dir, os.path.basename(message_config['html_file'])) with open(file_path, 'wb') as file_h: file_h.write(message_template_from_kpm(arcfile_h.read().decode(encoding), attachments).encode(encoding)) message_config['html_file'] = file_path elif 'html_file' in message_config: logger.warning('the kpm archive is missing the message_content.html file') raise errors.KingPhisherInputValidationError('data is missing from the message archive') kpm.close() return message_config
def message_data_from_kpm(target_file, dest_dir): """ Retrieve the stored details describing a message from a previously exported file. :param str target_file: The file to load as a message archive. :param str dest_dir: The directory to extract data and attachment files to. :return: The restored details from the message config. :rtype: dict """ if not archive.is_archive(target_file): logger.warning('the file is not recognized as a valid archive') raise KingPhisherInputValidationError('file is not in the correct format') kpm = archive.ArchiveFile(target_file, 'r') attachment_member_names = [n for n in kpm.file_names if n.startswith('attachments' + os.path.sep)] attachments = [] if not kpm.has_file('message_config.json'): logger.warning('the kpm archive is missing the message_config.json file') raise KingPhisherInputValidationError('data is missing from the message archive') message_config = kpm.get_data('message_config.json') message_config = json_ex.loads(message_config) if attachment_member_names: attachment_dir = os.path.join(dest_dir, 'attachments') if not os.path.isdir(attachment_dir): os.mkdir(attachment_dir) for file_name in attachment_member_names: arcfile_h = kpm.get_file(file_name) file_name = os.path.basename(file_name) file_path = os.path.join(attachment_dir, file_name) with open(file_path, 'wb') as file_h: shutil.copyfileobj(arcfile_h, file_h) attachments.append(file_path) logger.debug("extracted {0} attachment file{1} from the archive".format(len(attachments), 's' if len(attachments) > 1 else '')) for config_name, file_name in KPM_ARCHIVE_FILES.items(): if not file_name in kpm.file_names: if config_name in message_config: logger.warning("the kpm archive is missing the {0} file".format(file_name)) raise KingPhisherInputValidationError('data is missing from the message archive') continue if not message_config.get(config_name): logger.warning("the kpm message configuration is missing the {0} setting".format(config_name)) raise KingPhisherInputValidationError('data is missing from the message archive') arcfile_h = kpm.get_file(file_name) file_path = os.path.join(dest_dir, message_config[config_name]) with open(file_path, 'wb') as file_h: shutil.copyfileobj(arcfile_h, file_h) message_config[config_name] = file_path if 'message_content.html' in kpm.file_names: if not 'html_file' in message_config: logger.warning('the kpm message configuration is missing the html_file setting') raise KingPhisherInputValidationError('data is missing from the message archive') arcfile_h = kpm.get_file('message_content.html') file_path = os.path.join(dest_dir, message_config['html_file']) with open(file_path, 'wb') as file_h: file_h.write(message_template_from_kpm(arcfile_h.read(), attachments)) message_config['html_file'] = file_path elif 'html_file' in message_config: logger.warning('the kpm archive is missing the message_content.html file') raise KingPhisherInputValidationError('data is missing from the message archive') kpm.close() return message_config