mirror of https://github.com/MISP/PyMISP
chg: Add i8n for pdfexport, without all the fonts in the main repo
parent
166ef3866d
commit
b8759673b9
|
@ -1,3 +1,6 @@
|
||||||
[submodule "pymisp/data/misp-objects"]
|
[submodule "pymisp/data/misp-objects"]
|
||||||
path = pymisp/data/misp-objects
|
path = pymisp/data/misp-objects
|
||||||
url = https://github.com/MISP/misp-objects
|
url = https://github.com/MISP/misp-objects
|
||||||
|
[submodule "pymisp/tools/pdf_fonts"]
|
||||||
|
path = pymisp/tools/pdf_fonts
|
||||||
|
url = https://github.com/MISP/pdf_fonts
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit 7ff222022e6ad99e11a201f62d57da4bff1337ee
|
|
@ -8,6 +8,7 @@ import pprint
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
|
import os
|
||||||
|
|
||||||
if sys.version_info.major >= 3:
|
if sys.version_info.major >= 3:
|
||||||
from html import escape
|
from html import escape
|
||||||
|
@ -21,13 +22,16 @@ logger = logging.getLogger('pymisp')
|
||||||
# Potentially not installed imports
|
# Potentially not installed imports
|
||||||
try:
|
try:
|
||||||
from reportlab.pdfgen import canvas
|
from reportlab.pdfgen import canvas
|
||||||
from reportlab.pdfbase.pdfmetrics import stringWidth
|
from reportlab.pdfbase.pdfmetrics import stringWidth, registerFont, registerFontFamily
|
||||||
from reportlab.pdfbase.pdfdoc import PDFDictionary, PDFInfo
|
from reportlab.pdfbase.pdfdoc import PDFDictionary, PDFInfo
|
||||||
|
from reportlab.pdfbase.ttfonts import TTFont
|
||||||
from reportlab.lib import colors
|
from reportlab.lib import colors
|
||||||
from reportlab.lib.utils import ImageReader
|
from reportlab.lib.utils import ImageReader
|
||||||
from reportlab.lib.pagesizes import A4
|
from reportlab.lib.pagesizes import A4
|
||||||
|
from reportlab.lib.fonts import addMapping
|
||||||
|
|
||||||
from reportlab.platypus import SimpleDocTemplate, Paragraph, PageBreak, Spacer, Table, TableStyle, Flowable, Image, Indenter
|
from reportlab.platypus import SimpleDocTemplate, Paragraph, PageBreak, Spacer, Table, TableStyle, Flowable, Image, \
|
||||||
|
Indenter
|
||||||
|
|
||||||
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
|
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
|
||||||
from reportlab.lib.units import mm
|
from reportlab.lib.units import mm
|
||||||
|
@ -125,7 +129,7 @@ class Flowable_Tag(Flowable):
|
||||||
|
|
||||||
# Copy of pdfexport.py moduleconfig
|
# Copy of pdfexport.py moduleconfig
|
||||||
moduleconfig = ["MISP_base_url_for_dynamic_link", "MISP_name_for_metadata", "Activate_textual_description",
|
moduleconfig = ["MISP_base_url_for_dynamic_link", "MISP_name_for_metadata", "Activate_textual_description",
|
||||||
"Activate_galaxy_description"]
|
"Activate_galaxy_description", "Activate_related_events", "Activate_internationalization_fonts"]
|
||||||
|
|
||||||
# == Row colors of the table (alternating) ==
|
# == Row colors of the table (alternating) ==
|
||||||
EVEN_COLOR = colors.whitesmoke
|
EVEN_COLOR = colors.whitesmoke
|
||||||
|
@ -138,7 +142,6 @@ LINE_COLOR = colors.lightslategray
|
||||||
LINE_THICKNESS = 0.75
|
LINE_THICKNESS = 0.75
|
||||||
|
|
||||||
# == Columns colors, aligment, fonts, space, size, width, heights ==
|
# == Columns colors, aligment, fonts, space, size, width, heights ==
|
||||||
# FIRST_COL_FONT_COLOR = colors.darkslateblue # Test purposes
|
|
||||||
FIRST_COL_FONT_COLOR = colors.HexColor("#333333") # Same as GUI
|
FIRST_COL_FONT_COLOR = colors.HexColor("#333333") # Same as GUI
|
||||||
FIRST_COL_FONT = 'Helvetica-Bold'
|
FIRST_COL_FONT = 'Helvetica-Bold'
|
||||||
FIRST_COL_ALIGNEMENT = TA_CENTER
|
FIRST_COL_ALIGNEMENT = TA_CENTER
|
||||||
|
@ -158,24 +161,23 @@ SMALL_COL2_ALIGMENT = TA_JUSTIFY
|
||||||
|
|
||||||
EXPORT_DATE_FORMAT = '%Y-%m-%d %H:%M:%S'
|
EXPORT_DATE_FORMAT = '%Y-%m-%d %H:%M:%S'
|
||||||
COL_WIDTHS = ['25%', '75%'] # colWidths='*' # Not documented but does exist
|
COL_WIDTHS = ['25%', '75%'] # colWidths='*' # Not documented but does exist
|
||||||
# COL_WIDTHS = ['20%', '80%'] # colWidths='*' # Not documented but does exist
|
|
||||||
ROW_HEIGHT = 5 * mm # 4.5 * mm (a bit too short to allow vertical align TODO : Fix it)
|
ROW_HEIGHT = 5 * mm # 4.5 * mm (a bit too short to allow vertical align TODO : Fix it)
|
||||||
ROW_HEIGHT_FOR_TAGS = 4 * mm # 4.5 * mm (a bit too short to allow vertical align TODO : Fix it)
|
ROW_HEIGHT_FOR_TAGS = 4 * mm # 4.5 * mm (a bit too short to allow vertical align TODO : Fix it)
|
||||||
|
|
||||||
# == Whole document margins and size ==
|
# == Whole document margins and size ==
|
||||||
PAGESIZE = A4 # (140 * mm, 216 * mm) # width, height
|
PAGESIZE = A4 # (140 * mm, 216 * mm) # width, height
|
||||||
BASE_MARGIN = 5 * mm # Create a list here to specify each row separately
|
BASE_MARGIN = 5 * mm # Create a list here to specify each row separately
|
||||||
INDENT_SIZE = 6 * mm # The Indentation of attribute from object, etc.
|
INDENT_SIZE = 6 * mm # The Indentation of attribute from object, etc.
|
||||||
INDENT_SIZE_HEADING = 3 * mm # The Indentation of attribute from object, etc.
|
INDENT_SIZE_HEADING = 3 * mm # The Indentation of attribute from object, etc.
|
||||||
|
|
||||||
# == Parameters for error handling for content too long to fit on a page ==
|
# == Parameters for error handling for content too long to fit on a page ==
|
||||||
FRAME_MAX_HEIGHT = 200*mm # 500 # Ad hoc value for a A4 page
|
FRAME_MAX_HEIGHT = 200 * mm # 500 # Ad hoc value for a A4 page
|
||||||
FRAME_MAX_WIDTH = 145*mm - INDENT_SIZE # 356
|
FRAME_MAX_WIDTH = 145 * mm - INDENT_SIZE # 356
|
||||||
STR_TOO_LONG_WARNING = "<br/><b><font color=red>[Too long to fit on a single page. Cropped]</font></b>"
|
STR_TOO_LONG_WARNING = "<br/><b><font color=red>[Too long to fit on a single page. Cropped]</font></b>"
|
||||||
|
|
||||||
# == Parameters for error handling for image too big to fit on a page ==
|
# == Parameters for error handling for image too big to fit on a page ==
|
||||||
FRAME_PICTURE_MAX_HEIGHT = 200*mm # 195 * mm
|
FRAME_PICTURE_MAX_HEIGHT = 200 * mm # 195 * mm
|
||||||
FRAME_PICTURE_MAX_WIDTH = 145*mm - INDENT_SIZE # 88 * mm
|
FRAME_PICTURE_MAX_WIDTH = 145 * mm - INDENT_SIZE # 88 * mm
|
||||||
|
|
||||||
# == Parameters for links management ==
|
# == Parameters for links management ==
|
||||||
LINK_TYPE = "link" # Name of the type that define 'good' links
|
LINK_TYPE = "link" # Name of the type that define 'good' links
|
||||||
|
@ -190,6 +192,7 @@ BAD_LINK_COLOR = 'red'
|
||||||
LOW_THREAT_COLOR = 'green'
|
LOW_THREAT_COLOR = 'green'
|
||||||
MEDIUM_THREAT_COLOR = 'orange'
|
MEDIUM_THREAT_COLOR = 'orange'
|
||||||
HIGH_THREAT_COLOR = 'red'
|
HIGH_THREAT_COLOR = 'red'
|
||||||
|
EXTERNAL_ANALYSIS_PREFIX = "<i>External analysis from an attribute : </i>"
|
||||||
|
|
||||||
# == Parameters for improvement of event's metadata ==
|
# == Parameters for improvement of event's metadata ==
|
||||||
|
|
||||||
|
@ -209,9 +212,9 @@ MISC_SIGHT_COLOR = 'orange'
|
||||||
|
|
||||||
# == Parameters for galaxies ==
|
# == Parameters for galaxies ==
|
||||||
DO_SMALL_GALAXIES = True
|
DO_SMALL_GALAXIES = True
|
||||||
FIRST_LEVEL_GALAXY_WIDTHS = ["15%","85%"]
|
FIRST_LEVEL_GALAXY_WIDTHS = ["15%", "85%"]
|
||||||
SECOND_LEVEL_GALAXY_WIDTHS = ["20%","80%"]
|
SECOND_LEVEL_GALAXY_WIDTHS = ["20%", "80%"]
|
||||||
CLUSTER_COLORS = [0] # or 1
|
CLUSTER_COLORS = [0] # or 1
|
||||||
OFFSET = 1
|
OFFSET = 1
|
||||||
|
|
||||||
########################################################################
|
########################################################################
|
||||||
|
@ -258,7 +261,8 @@ def uuid_to_url(baseurl, uuid):
|
||||||
return baseurl + "events/view/" + uuid
|
return baseurl + "events/view/" + uuid
|
||||||
|
|
||||||
|
|
||||||
def create_flowable_table_from_data(data, col_w=COL_WIDTHS, color_alternation=None, line_alternation=None, galaxy_colors=False):
|
def create_flowable_table_from_data(data, col_w=COL_WIDTHS, color_alternation=None, line_alternation=None,
|
||||||
|
galaxy_colors=False):
|
||||||
'''
|
'''
|
||||||
Given a list of flowables items (2D/list of list), creates a Table with styles.
|
Given a list of flowables items (2D/list of list), creates a Table with styles.
|
||||||
:param data: list of list of items (flowables is better)
|
:param data: list of list of items (flowables is better)
|
||||||
|
@ -272,8 +276,8 @@ def create_flowable_table_from_data(data, col_w=COL_WIDTHS, color_alternation=No
|
||||||
# rowHeights=ROW_HEIGHT if you want a fixed height. /!\ Problems with paragraphs that are spreading everywhere
|
# rowHeights=ROW_HEIGHT if you want a fixed height. /!\ Problems with paragraphs that are spreading everywhere
|
||||||
|
|
||||||
# Create styles and set parameters
|
# Create styles and set parameters
|
||||||
alternate_colors_style = alternate_colors_style_generator(data,color_alternation, galaxy_colors)
|
alternate_colors_style = alternate_colors_style_generator(data, color_alternation, galaxy_colors)
|
||||||
lines_style = lines_style_generator(data,line_alternation)
|
lines_style = lines_style_generator(data, line_alternation)
|
||||||
general_style = general_style_generator()
|
general_style = general_style_generator()
|
||||||
|
|
||||||
# Make the table nicer
|
# Make the table nicer
|
||||||
|
@ -310,7 +314,7 @@ def alternate_colors_style_generator(data, color_alternation, galaxy_colors=True
|
||||||
|
|
||||||
# For each line, generate a tuple giving to a line a color
|
# For each line, generate a tuple giving to a line a color
|
||||||
for each in range(data_len):
|
for each in range(data_len):
|
||||||
if color_alternation[each%len(color_alternation)] % 2 == 0:
|
if color_alternation[each % len(color_alternation)] % 2 == 0:
|
||||||
bg_color = EVEN_COLOR if not galaxy_colors else EVEN_COLOR_GALAXY
|
bg_color = EVEN_COLOR if not galaxy_colors else EVEN_COLOR_GALAXY
|
||||||
else:
|
else:
|
||||||
bg_color = ODD_COLOR if not galaxy_colors else ODD_COLOR_GALAXY
|
bg_color = ODD_COLOR if not galaxy_colors else ODD_COLOR_GALAXY
|
||||||
|
@ -338,7 +342,7 @@ def lines_style_generator(data, line_alternation):
|
||||||
|
|
||||||
# Last line
|
# Last line
|
||||||
lines_list.append(('LINEBELOW', (0, len(data) - 1), (-1, len(data) - 1), LINE_THICKNESS, LINE_COLOR))
|
lines_list.append(('LINEBELOW', (0, len(data) - 1), (-1, len(data) - 1), LINE_THICKNESS, LINE_COLOR))
|
||||||
elif line_alternation == [] :
|
elif line_alternation == []:
|
||||||
# Do nothing
|
# Do nothing
|
||||||
return lines_list
|
return lines_list
|
||||||
else:
|
else:
|
||||||
|
@ -347,13 +351,13 @@ def lines_style_generator(data, line_alternation):
|
||||||
|
|
||||||
# For each line, generate a tuple giving to a line a color
|
# For each line, generate a tuple giving to a line a color
|
||||||
for each in range(data_len):
|
for each in range(data_len):
|
||||||
if each == 0 or line_alternation[each%len(line_alternation)] != line_alternation[(each-1)%len(line_alternation)]:
|
if each == 0 or line_alternation[each % len(line_alternation)] != line_alternation[
|
||||||
|
(each - 1) % len(line_alternation)]:
|
||||||
lines_list.append(('LINEABOVE', (0, each), (-1, each), LINE_THICKNESS, LINE_COLOR))
|
lines_list.append(('LINEABOVE', (0, each), (-1, each), LINE_THICKNESS, LINE_COLOR))
|
||||||
|
|
||||||
# Last line
|
# Last line
|
||||||
lines_list.append(('LINEBELOW', (0, len(data) - 1), (-1, len(data) - 1), LINE_THICKNESS, LINE_COLOR))
|
lines_list.append(('LINEBELOW', (0, len(data) - 1), (-1, len(data) - 1), LINE_THICKNESS, LINE_COLOR))
|
||||||
|
|
||||||
|
|
||||||
return lines_list
|
return lines_list
|
||||||
|
|
||||||
|
|
||||||
|
@ -375,6 +379,36 @@ def general_style_generator():
|
||||||
return lines_list
|
return lines_list
|
||||||
|
|
||||||
|
|
||||||
|
def internationalize_font():
|
||||||
|
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + "/tools"
|
||||||
|
|
||||||
|
global FIRST_COL_FONT
|
||||||
|
global SECOND_COL_FONT
|
||||||
|
|
||||||
|
''' # Available fonts :
|
||||||
|
NotoSansCJKtc - DemiLight.ttf
|
||||||
|
NotoSansCJKtc - Regular.ttf
|
||||||
|
NotoSansCJKtc - Black.ttf
|
||||||
|
NotoSansCJKtc - Light.ttf
|
||||||
|
NotoSansCJKtc - Thin.ttf
|
||||||
|
NotoSansCJKtc - Bold.ttf
|
||||||
|
NotoSansCJKtc - Medium.ttf
|
||||||
|
'''
|
||||||
|
|
||||||
|
noto_bold = BASE_DIR + "/pdf_fonts/Noto_TTF/NotoSansCJKtc-Bold.ttf"
|
||||||
|
noto = BASE_DIR + "/pdf_fonts/Noto_TTF/NotoSansCJKtc-DemiLight.ttf"
|
||||||
|
|
||||||
|
if os.path.isfile(noto_bold) and os.path.isfile(noto):
|
||||||
|
registerFont(TTFont("Noto", noto))
|
||||||
|
registerFont(TTFont("Noto-bold", noto_bold))
|
||||||
|
|
||||||
|
FIRST_COL_FONT = 'Noto-bold'
|
||||||
|
SECOND_COL_FONT = 'Noto'
|
||||||
|
else:
|
||||||
|
logger.error(
|
||||||
|
"Trying to load a custom (internationalization) font, unable to access the file : " + noto_bold)
|
||||||
|
|
||||||
|
|
||||||
def get_table_styles():
|
def get_table_styles():
|
||||||
'''
|
'''
|
||||||
Create and returns the two mains styles for the columns of the document.
|
Create and returns the two mains styles for the columns of the document.
|
||||||
|
@ -426,6 +460,7 @@ def get_clusters_table_styles():
|
||||||
|
|
||||||
return custom_body_style_col_1, custom_body_style_col_2
|
return custom_body_style_col_1, custom_body_style_col_2
|
||||||
|
|
||||||
|
|
||||||
########################################################################
|
########################################################################
|
||||||
# Checks
|
# Checks
|
||||||
|
|
||||||
|
@ -474,8 +509,8 @@ class Value_Formatter():
|
||||||
# ----------------------------------------------------------------------
|
# ----------------------------------------------------------------------
|
||||||
########################################################################
|
########################################################################
|
||||||
# General attribut formater
|
# General attribut formater
|
||||||
def get_col1_paragraph(self, dirty_string, do_small=False):
|
def get_col1_paragraph(self, dirty_string, do_small=False):
|
||||||
if do_small :
|
if do_small:
|
||||||
return self.get_unoverflowable_paragraph(dirty_string, self.col1_small_style, do_small=do_small)
|
return self.get_unoverflowable_paragraph(dirty_string, self.col1_small_style, do_small=do_small)
|
||||||
return self.get_unoverflowable_paragraph(dirty_string, self.col1_style, do_small=do_small)
|
return self.get_unoverflowable_paragraph(dirty_string, self.col1_style, do_small=do_small)
|
||||||
|
|
||||||
|
@ -494,13 +529,12 @@ class Value_Formatter():
|
||||||
else:
|
else:
|
||||||
sanitized_str = dirty_string
|
sanitized_str = dirty_string
|
||||||
|
|
||||||
if curr_style is None :
|
if curr_style is None:
|
||||||
if do_small :
|
if do_small:
|
||||||
curr_style = self.col2_small_style
|
curr_style = self.col2_small_style
|
||||||
else :
|
else:
|
||||||
curr_style = self.col2_style
|
curr_style = self.col2_style
|
||||||
|
|
||||||
|
|
||||||
# Get the space that the paragraph needs to be printed
|
# Get the space that the paragraph needs to be printed
|
||||||
w, h = Paragraph(sanitized_str, curr_style).wrap(FRAME_MAX_WIDTH, FRAME_MAX_HEIGHT)
|
w, h = Paragraph(sanitized_str, curr_style).wrap(FRAME_MAX_WIDTH, FRAME_MAX_HEIGHT)
|
||||||
|
|
||||||
|
@ -780,7 +814,8 @@ class Value_Formatter():
|
||||||
if is_safe_dict_attribute(misp_galaxy, item[1]):
|
if is_safe_dict_attribute(misp_galaxy, item[1]):
|
||||||
return self.get_unoverflowable_paragraph(safe_string(misp_galaxy[item[1]])
|
return self.get_unoverflowable_paragraph(safe_string(misp_galaxy[item[1]])
|
||||||
+ " <i>from</i> " + safe_string(misp_galaxy[item[3]]) + ":"
|
+ " <i>from</i> " + safe_string(misp_galaxy[item[3]]) + ":"
|
||||||
+ safe_string(misp_galaxy[item[4]]), do_escape_string=False, do_small=True)
|
+ safe_string(misp_galaxy[item[4]]), do_escape_string=False,
|
||||||
|
do_small=True)
|
||||||
return self.get_unoverflowable_paragraph(item[2], do_small=True)
|
return self.get_unoverflowable_paragraph(item[2], do_small=True)
|
||||||
|
|
||||||
def get_galaxy_cluster_name_value(self, misp_cluster, do_small=False):
|
def get_galaxy_cluster_name_value(self, misp_cluster, do_small=False):
|
||||||
|
@ -790,19 +825,20 @@ class Value_Formatter():
|
||||||
if is_safe_dict_attribute(misp_cluster, item[1]):
|
if is_safe_dict_attribute(misp_cluster, item[1]):
|
||||||
tmp_text += safe_string(misp_cluster[item[1]])
|
tmp_text += safe_string(misp_cluster[item[1]])
|
||||||
|
|
||||||
#if is_safe_dict_attribute(misp_cluster, item[3]) :
|
# if is_safe_dict_attribute(misp_cluster, item[3]) :
|
||||||
# tmp_text += "<br/><i>Source :</i> " + misp_cluster[item[3]]
|
# tmp_text += "<br/><i>Source :</i> " + misp_cluster[item[3]]
|
||||||
|
|
||||||
if is_safe_dict_attribute(misp_cluster, item[4]) and is_safe_dict_attribute(misp_cluster[item[4]], item[5]):
|
if is_safe_dict_attribute(misp_cluster, item[4]) and is_safe_dict_attribute(misp_cluster[item[4]], item[5]):
|
||||||
tmp_text += " <br/><i>Synonyms :</i> "
|
tmp_text += " <br/><i>Synonyms :</i> "
|
||||||
for i, synonyme in enumerate(misp_cluster[item[4]][item[5]]) :
|
for i, synonyme in enumerate(misp_cluster[item[4]][item[5]]):
|
||||||
if i != 0 :
|
if i != 0:
|
||||||
tmp_text += " / "
|
tmp_text += " / "
|
||||||
tmp_text += safe_string(synonyme)
|
tmp_text += safe_string(synonyme)
|
||||||
|
|
||||||
return self.get_unoverflowable_paragraph(tmp_text, do_escape_string=False, do_small=do_small)
|
return self.get_unoverflowable_paragraph(tmp_text, do_escape_string=False, do_small=do_small)
|
||||||
return self.get_unoverflowable_paragraph(item[2], do_small=do_small)
|
return self.get_unoverflowable_paragraph(item[2], do_small=do_small)
|
||||||
|
|
||||||
|
|
||||||
class Event_Metadata():
|
class Event_Metadata():
|
||||||
|
|
||||||
# ----------------------------------------------------------------------
|
# ----------------------------------------------------------------------
|
||||||
|
@ -884,6 +920,10 @@ class Event_Metadata():
|
||||||
|
|
||||||
flowable_table.append(create_flowable_table_from_data(data))
|
flowable_table.append(create_flowable_table_from_data(data))
|
||||||
|
|
||||||
|
# Correlation
|
||||||
|
item = ["Related Events", 'RelatedEvent', "None"]
|
||||||
|
if is_safe_attribute_table(misp_event, item[1]) and is_in_config(self.config, 4):
|
||||||
|
flowable_table += self.get_correlation_values(misp_event, item)
|
||||||
|
|
||||||
# Galaxies
|
# Galaxies
|
||||||
item = ["Related Galaxies", 'Galaxy', "None"]
|
item = ["Related Galaxies", 'Galaxy', "None"]
|
||||||
|
@ -894,6 +934,36 @@ class Event_Metadata():
|
||||||
|
|
||||||
return flowable_table
|
return flowable_table
|
||||||
|
|
||||||
|
def create_reduced_flowable_table_from_event(self, misp_event):
|
||||||
|
'''
|
||||||
|
Returns Table presenting a MISP event
|
||||||
|
:param misp_event: A misp event (complete or not)
|
||||||
|
:return: a table that can be added to a pdf
|
||||||
|
'''
|
||||||
|
|
||||||
|
data = []
|
||||||
|
flowable_table = []
|
||||||
|
|
||||||
|
# Manual addition
|
||||||
|
# UUID
|
||||||
|
item = ["UUID", 'uuid', "None"]
|
||||||
|
data.append([self.value_formatter.get_col1_paragraph(item[0]),
|
||||||
|
self.value_formatter.get_value_link_to_event(misp_event, item)])
|
||||||
|
|
||||||
|
# Info
|
||||||
|
item = ["Info", 'info', "None"]
|
||||||
|
data.append([self.value_formatter.get_col1_paragraph(item[0]),
|
||||||
|
self.value_formatter.get_value_link_to_event(misp_event, item)])
|
||||||
|
|
||||||
|
# Timestamp
|
||||||
|
item = ["Event date", 'timestamp', "None"]
|
||||||
|
data.append([self.value_formatter.get_col1_paragraph(item[0]),
|
||||||
|
self.value_formatter.get_timestamp_value(misp_event, item)])
|
||||||
|
|
||||||
|
flowable_table.append(create_flowable_table_from_data(data))
|
||||||
|
|
||||||
|
return flowable_table
|
||||||
|
|
||||||
def create_flowable_description_from_event(self, misp_event):
|
def create_flowable_description_from_event(self, misp_event):
|
||||||
'''
|
'''
|
||||||
Returns a Paragraph presenting a MISP event
|
Returns a Paragraph presenting a MISP event
|
||||||
|
@ -988,6 +1058,14 @@ class Event_Metadata():
|
||||||
|
|
||||||
text += " associated objects."
|
text += " associated objects."
|
||||||
|
|
||||||
|
curr_attributes = Attributes(self.config, self.value_formatter)
|
||||||
|
tmp_text = curr_attributes.get_external_analysis(misp_event)
|
||||||
|
|
||||||
|
if tmp_text != "":
|
||||||
|
text += "<br/>"
|
||||||
|
text += tmp_text
|
||||||
|
text += "<br/>"
|
||||||
|
|
||||||
'''
|
'''
|
||||||
For more information on the event, please consult the rest of the document
|
For more information on the event, please consult the rest of the document
|
||||||
'''
|
'''
|
||||||
|
@ -998,6 +1076,33 @@ class Event_Metadata():
|
||||||
|
|
||||||
return Paragraph(text, description_style)
|
return Paragraph(text, description_style)
|
||||||
|
|
||||||
|
def get_correlation_values(self, misp_event, item):
|
||||||
|
'''
|
||||||
|
Returns a flowable paragraph to add to the pdf given the misp_event correlated events
|
||||||
|
:param misp_event: A misp event with or without "RelatedEvent" attributes
|
||||||
|
:param item: as defined in class definition
|
||||||
|
:param col2_style: style to be applied on the returned paragraph
|
||||||
|
:return: a Paragraph to add in the pdf, regarding the values of "RelatedEvent"
|
||||||
|
'''
|
||||||
|
flowable_table = []
|
||||||
|
|
||||||
|
flowable_table.append(PageBreak())
|
||||||
|
flowable_table.append(Paragraph("Related Events", self.sample_style_sheet['Heading3']))
|
||||||
|
|
||||||
|
if is_safe_attribute_table(misp_event, item[1]):
|
||||||
|
for i, evt in enumerate(getattr(misp_event, item[1])):
|
||||||
|
flowable_table.append(Indenter(left=INDENT_SIZE_HEADING))
|
||||||
|
flowable_table.append(
|
||||||
|
Paragraph("Related Event #" + str(i + OFFSET), self.sample_style_sheet['Heading4']))
|
||||||
|
flowable_table.append(Indenter(left=-INDENT_SIZE_HEADING))
|
||||||
|
|
||||||
|
flowable_table += self.create_reduced_flowable_table_from_event(evt)
|
||||||
|
i += 1
|
||||||
|
else:
|
||||||
|
return flowable_table.append(self.value_formatter.get_unoverflowable_paragraph(item[2]))
|
||||||
|
|
||||||
|
return flowable_table
|
||||||
|
|
||||||
|
|
||||||
class Attributes():
|
class Attributes():
|
||||||
|
|
||||||
|
@ -1024,7 +1129,7 @@ class Attributes():
|
||||||
for item in getattr(misp_event, "Attribute"):
|
for item in getattr(misp_event, "Attribute"):
|
||||||
# you can use a spacer instead of title to separate paragraph: flowable_table.append(Spacer(1, 5 * mm))
|
# you can use a spacer instead of title to separate paragraph: flowable_table.append(Spacer(1, 5 * mm))
|
||||||
flowable_table.append(Indenter(left=INDENT_SIZE_HEADING))
|
flowable_table.append(Indenter(left=INDENT_SIZE_HEADING))
|
||||||
flowable_table.append(Paragraph("Attribute #" + str(i+OFFSET), self.sample_style_sheet['Heading4']))
|
flowable_table.append(Paragraph("Attribute #" + str(i + OFFSET), self.sample_style_sheet['Heading4']))
|
||||||
flowable_table.append(Indenter(left=-INDENT_SIZE_HEADING))
|
flowable_table.append(Indenter(left=-INDENT_SIZE_HEADING))
|
||||||
|
|
||||||
flowable_table += self.create_flowable_table_from_one_attribute(item)
|
flowable_table += self.create_flowable_table_from_one_attribute(item)
|
||||||
|
@ -1098,10 +1203,9 @@ class Attributes():
|
||||||
|
|
||||||
flowable_table.append(create_flowable_table_from_data(data))
|
flowable_table.append(create_flowable_table_from_data(data))
|
||||||
|
|
||||||
|
|
||||||
# Galaxies
|
# Galaxies
|
||||||
item = ["Related Galaxies", 'Galaxy', "None"]
|
item = ["Related Galaxies", 'Galaxy', "None"]
|
||||||
if is_safe_attribute_table(misp_attribute, item[1]) and is_in_config(self.config, 3) :
|
if is_safe_attribute_table(misp_attribute, item[1]) and is_in_config(self.config, 3):
|
||||||
curr_Galaxy = Galaxy(self.config, self.value_formatter)
|
curr_Galaxy = Galaxy(self.config, self.value_formatter)
|
||||||
flowable_table.append(Indenter(left=INDENT_SIZE))
|
flowable_table.append(Indenter(left=INDENT_SIZE))
|
||||||
flowable_table += curr_Galaxy.get_galaxy_value(misp_attribute, item)
|
flowable_table += curr_Galaxy.get_galaxy_value(misp_attribute, item)
|
||||||
|
@ -1109,6 +1213,27 @@ class Attributes():
|
||||||
|
|
||||||
return flowable_table
|
return flowable_table
|
||||||
|
|
||||||
|
def get_external_analysis(self, misp_event):
|
||||||
|
'''
|
||||||
|
Returns a string representing the list of external analysis comments of a misp event.
|
||||||
|
:param misp_event: A misp event
|
||||||
|
:return: a table of flowables
|
||||||
|
'''
|
||||||
|
text = ""
|
||||||
|
|
||||||
|
if is_safe_attribute_table(misp_event, "Attribute"):
|
||||||
|
# There is some attributes for this object
|
||||||
|
for attribute in getattr(misp_event, "Attribute"):
|
||||||
|
# If the current event is an external analysis and a comment
|
||||||
|
if is_safe_attribute(attribute, "value") and is_safe_attribute(attribute,
|
||||||
|
"category") and is_safe_attribute(
|
||||||
|
attribute, "type") and getattr(attribute, "category") == "External analysis" and getattr(
|
||||||
|
attribute, "type") == "comment":
|
||||||
|
# We add it to the description
|
||||||
|
text += "<br/>" + EXTERNAL_ANALYSIS_PREFIX + safe_string(getattr(attribute, "value"))
|
||||||
|
|
||||||
|
return text
|
||||||
|
|
||||||
|
|
||||||
class Tags():
|
class Tags():
|
||||||
|
|
||||||
|
@ -1215,7 +1340,6 @@ class Sightings():
|
||||||
return answer_sighting
|
return answer_sighting
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Object():
|
class Object():
|
||||||
|
|
||||||
# ----------------------------------------------------------------------
|
# ----------------------------------------------------------------------
|
||||||
|
@ -1244,7 +1368,7 @@ class Object():
|
||||||
for item in getattr(misp_event, "Object"):
|
for item in getattr(misp_event, "Object"):
|
||||||
# you can use a spacer instead of title to separate paragraph: flowable_table.append(Spacer(1, 5 * mm))
|
# you can use a spacer instead of title to separate paragraph: flowable_table.append(Spacer(1, 5 * mm))
|
||||||
flowable_table.append(Indenter(left=INDENT_SIZE_HEADING))
|
flowable_table.append(Indenter(left=INDENT_SIZE_HEADING))
|
||||||
flowable_table.append(Paragraph("Object #" + str(i+OFFSET), self.sample_style_sheet['Heading3']))
|
flowable_table.append(Paragraph("Object #" + str(i + OFFSET), self.sample_style_sheet['Heading3']))
|
||||||
flowable_table.append(Indenter(left=-INDENT_SIZE_HEADING))
|
flowable_table.append(Indenter(left=-INDENT_SIZE_HEADING))
|
||||||
flowable_table += self.create_flowable_table_from_one_object(item, config)
|
flowable_table += self.create_flowable_table_from_one_object(item, config)
|
||||||
i += 1
|
i += 1
|
||||||
|
@ -1254,7 +1378,6 @@ class Object():
|
||||||
|
|
||||||
return flowable_table
|
return flowable_table
|
||||||
|
|
||||||
|
|
||||||
def create_flowable_table_from_one_object(self, misp_object, config=None):
|
def create_flowable_table_from_one_object(self, misp_object, config=None):
|
||||||
'''
|
'''
|
||||||
Returns a table (flowable) representing the object
|
Returns a table (flowable) representing the object
|
||||||
|
@ -1284,7 +1407,8 @@ class Object():
|
||||||
|
|
||||||
# Timestamp
|
# Timestamp
|
||||||
item = ["Object date", 'timestamp', "None"]
|
item = ["Object date", 'timestamp', "None"]
|
||||||
data.append([self.value_formatter.get_col1_paragraph(item[0]), self.value_formatter.get_timestamp_value(misp_object, item)])
|
data.append([self.value_formatter.get_col1_paragraph(item[0]),
|
||||||
|
self.value_formatter.get_timestamp_value(misp_object, item)])
|
||||||
|
|
||||||
# Transform list of value in a table
|
# Transform list of value in a table
|
||||||
data = [create_flowable_table_from_data(data)]
|
data = [create_flowable_table_from_data(data)]
|
||||||
|
@ -1328,12 +1452,12 @@ class Galaxy():
|
||||||
# Galaxies
|
# Galaxies
|
||||||
# item = ["Related Galaxies", 'Galaxy', "None"]
|
# item = ["Related Galaxies", 'Galaxy', "None"]
|
||||||
if is_safe_attribute_table(misp_event, item[1]) and is_in_config(self.config, 3):
|
if is_safe_attribute_table(misp_event, item[1]) and is_in_config(self.config, 3):
|
||||||
galaxy_title = Paragraph(item[0], self.sample_style_sheet['Heading5'])
|
galaxy_title = Paragraph(safe_string(item[0]), self.sample_style_sheet['Heading5'])
|
||||||
flowable_table.append(Indenter(left=INDENT_SIZE_HEADING))
|
flowable_table.append(Indenter(left=INDENT_SIZE_HEADING))
|
||||||
flowable_table.append(galaxy_title)
|
flowable_table.append(galaxy_title)
|
||||||
flowable_table.append(Indenter(left=-INDENT_SIZE_HEADING))
|
flowable_table.append(Indenter(left=-INDENT_SIZE_HEADING))
|
||||||
flowable_table += self.create_flowable_table_from_galaxies(misp_event)
|
flowable_table += self.create_flowable_table_from_galaxies(misp_event)
|
||||||
else :
|
else:
|
||||||
flowable_table.append(self.value_formatter.get_unoverflowable_paragraph(item[2]))
|
flowable_table.append(self.value_formatter.get_unoverflowable_paragraph(item[2]))
|
||||||
|
|
||||||
return flowable_table
|
return flowable_table
|
||||||
|
@ -1348,7 +1472,8 @@ class Galaxy():
|
||||||
scheme_alternation = []
|
scheme_alternation = []
|
||||||
curr_color = 0
|
curr_color = 0
|
||||||
i = 0
|
i = 0
|
||||||
|
small_title_style = ParagraphStyle(name='Column_1', parent=self.sample_style_sheet['Heading6'],
|
||||||
|
fontName=FIRST_COL_FONT, alignment=TA_LEFT)
|
||||||
|
|
||||||
if is_safe_attribute_table(misp_event, "Galaxy"):
|
if is_safe_attribute_table(misp_event, "Galaxy"):
|
||||||
# There is some galaxies for this object
|
# There is some galaxies for this object
|
||||||
|
@ -1356,8 +1481,8 @@ class Galaxy():
|
||||||
for curr_galaxy in getattr(misp_event, "Galaxy"):
|
for curr_galaxy in getattr(misp_event, "Galaxy"):
|
||||||
# For each galaxy of the misp object
|
# For each galaxy of the misp object
|
||||||
|
|
||||||
txt_title = "Galaxy #" + str(i+OFFSET) + " - " + safe_string(curr_galaxy["name"])
|
txt_title = "Galaxy #" + str(i + OFFSET) + " - " + safe_string(curr_galaxy["name"])
|
||||||
galaxy_title = Paragraph(txt_title, self.sample_style_sheet['Heading6'])
|
galaxy_title = Paragraph(txt_title, small_title_style)
|
||||||
flowable_table.append(Indenter(left=INDENT_SIZE_HEADING))
|
flowable_table.append(Indenter(left=INDENT_SIZE_HEADING))
|
||||||
flowable_table.append(galaxy_title)
|
flowable_table.append(galaxy_title)
|
||||||
flowable_table.append(Indenter(left=-INDENT_SIZE_HEADING))
|
flowable_table.append(Indenter(left=-INDENT_SIZE_HEADING))
|
||||||
|
@ -1403,7 +1528,8 @@ class Galaxy():
|
||||||
item = ["Description", 'description', "None"]
|
item = ["Description", 'description', "None"]
|
||||||
if is_safe_dict_attribute(misp_galaxy, item[1]):
|
if is_safe_dict_attribute(misp_galaxy, item[1]):
|
||||||
data.append([self.value_formatter.get_col1_paragraph(item[0], do_small=DO_SMALL_GALAXIES),
|
data.append([self.value_formatter.get_col1_paragraph(item[0], do_small=DO_SMALL_GALAXIES),
|
||||||
self.value_formatter.get_unoverflowable_paragraph(misp_galaxy[item[1]], do_small=DO_SMALL_GALAXIES)])
|
self.value_formatter.get_unoverflowable_paragraph(misp_galaxy[item[1]],
|
||||||
|
do_small=DO_SMALL_GALAXIES)])
|
||||||
nb_added_item += 1
|
nb_added_item += 1
|
||||||
|
|
||||||
flowable_table = []
|
flowable_table = []
|
||||||
|
@ -1412,7 +1538,6 @@ class Galaxy():
|
||||||
return flowable_table, nb_added_item
|
return flowable_table, nb_added_item
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Galaxy_cluster():
|
class Galaxy_cluster():
|
||||||
|
|
||||||
# ----------------------------------------------------------------------
|
# ----------------------------------------------------------------------
|
||||||
|
@ -1435,26 +1560,29 @@ class Galaxy_cluster():
|
||||||
if is_safe_dict_attribute(misp_galaxy, "GalaxyCluster"):
|
if is_safe_dict_attribute(misp_galaxy, "GalaxyCluster"):
|
||||||
# There is some clusters for this object
|
# There is some clusters for this object
|
||||||
for i, curr_cluster in enumerate(misp_galaxy["GalaxyCluster"]):
|
for i, curr_cluster in enumerate(misp_galaxy["GalaxyCluster"]):
|
||||||
|
|
||||||
# If title is needed :
|
# If title is needed :
|
||||||
# galaxy_title = [Paragraph("Cluster #" + str(i), self.sample_style_sheet['Heading6'])]
|
# galaxy_title = [Paragraph("Cluster #" + str(i), self.sample_style_sheet['Heading6'])]
|
||||||
# data.append(galaxy_title)
|
# data.append(galaxy_title)
|
||||||
|
|
||||||
|
|
||||||
item[0] = "Cluster #" + str(i + OFFSET)
|
item[0] = "Cluster #" + str(i + OFFSET)
|
||||||
|
|
||||||
# For each cluster
|
# For each cluster
|
||||||
tmp_data = self.create_flowable_table_from_one_galaxy_cluster(curr_cluster)
|
tmp_data = self.create_flowable_table_from_one_galaxy_cluster(curr_cluster)
|
||||||
tmp_flowable_table = []
|
tmp_flowable_table = []
|
||||||
tmp_flowable_table.append(create_flowable_table_from_data(tmp_data, col_w=SECOND_LEVEL_GALAXY_WIDTHS, color_alternation = CLUSTER_COLORS, line_alternation=[], galaxy_colors=True))
|
tmp_flowable_table.append(create_flowable_table_from_data(tmp_data, col_w=SECOND_LEVEL_GALAXY_WIDTHS,
|
||||||
data.append([self.value_formatter.get_col1_paragraph(item[0], do_small=DO_SMALL_GALAXIES), tmp_flowable_table]) # Cluster #X - 3 lines
|
color_alternation=CLUSTER_COLORS,
|
||||||
|
line_alternation=[], galaxy_colors=True))
|
||||||
|
data.append([self.value_formatter.get_col1_paragraph(item[0], do_small=DO_SMALL_GALAXIES),
|
||||||
|
tmp_flowable_table]) # Cluster #X - 3 lines
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# No galaxies for this object
|
# No galaxies for this object
|
||||||
data = [self.value_formatter.get_unoverflowable_paragraph("No galaxy cluster", do_small=DO_SMALL_GALAXIES)]
|
data = [self.value_formatter.get_unoverflowable_paragraph("No galaxy cluster", do_small=DO_SMALL_GALAXIES)]
|
||||||
|
|
||||||
flowable_table = []
|
flowable_table = []
|
||||||
flowable_table.append(create_flowable_table_from_data(data, col_w=FIRST_LEVEL_GALAXY_WIDTHS, color_alternation = CLUSTER_COLORS, galaxy_colors=True))
|
flowable_table.append(
|
||||||
|
create_flowable_table_from_data(data, col_w=FIRST_LEVEL_GALAXY_WIDTHS, color_alternation=CLUSTER_COLORS,
|
||||||
|
galaxy_colors=True))
|
||||||
|
|
||||||
return flowable_table
|
return flowable_table
|
||||||
|
|
||||||
|
@ -1469,13 +1597,13 @@ class Galaxy_cluster():
|
||||||
# Name
|
# Name
|
||||||
item = ["Name", 'name', "None"]
|
item = ["Name", 'name', "None"]
|
||||||
data.append([self.value_formatter.get_col1_paragraph(item[0], do_small=True),
|
data.append([self.value_formatter.get_col1_paragraph(item[0], do_small=True),
|
||||||
self.value_formatter.get_galaxy_cluster_name_value(misp_cluster, do_small=True)])
|
self.value_formatter.get_galaxy_cluster_name_value(misp_cluster, do_small=True)])
|
||||||
|
|
||||||
if misp_cluster['value'] != misp_cluster['description'] : # Prevent name that are same as description
|
if misp_cluster['value'] != misp_cluster['description']: # Prevent name that are same as description
|
||||||
# Description
|
# Description
|
||||||
item = ["Description", 'description', "None"]
|
item = ["Description", 'description', "None"]
|
||||||
data.append([self.value_formatter.get_col1_paragraph(item[0], do_small=True),
|
data.append([self.value_formatter.get_col1_paragraph(item[0], do_small=True),
|
||||||
self.value_formatter.get_unoverflowable_paragraph(misp_cluster[item[1]], do_small=True)])
|
self.value_formatter.get_unoverflowable_paragraph(misp_cluster[item[1]], do_small=True)])
|
||||||
|
|
||||||
# Refs ?
|
# Refs ?
|
||||||
# item = ["Description", 'description', "None"]
|
# item = ["Description", 'description', "None"]
|
||||||
|
@ -1572,7 +1700,8 @@ def collect_parts(misp_event, config=None):
|
||||||
curr_val_f = Value_Formatter(config, col1_style, col2_style, col1_small_style, col2_small_style)
|
curr_val_f = Value_Formatter(config, col1_style, col2_style, col1_small_style, col2_small_style)
|
||||||
|
|
||||||
# Create stuff
|
# Create stuff
|
||||||
title_style = ParagraphStyle(name='Column_1', parent=sample_style_sheet['Heading1'], alignment=TA_CENTER)
|
title_style = ParagraphStyle(name='Column_1', parent=sample_style_sheet['Heading1'], fontName=FIRST_COL_FONT,
|
||||||
|
alignment=TA_CENTER)
|
||||||
title = curr_val_f.get_value_link_to_event(misp_event, ["Info", 'info', "None"], title_style, color=False)
|
title = curr_val_f.get_value_link_to_event(misp_event, ["Info", 'info', "None"], title_style, color=False)
|
||||||
# Add all parts to final PDF
|
# Add all parts to final PDF
|
||||||
flowables.append(title)
|
flowables.append(title)
|
||||||
|
@ -1593,7 +1722,7 @@ def collect_parts(misp_event, config=None):
|
||||||
flowables.append(subtitle)
|
flowables.append(subtitle)
|
||||||
flowables += table_general_metainformation
|
flowables += table_general_metainformation
|
||||||
|
|
||||||
if is_safe_attribute_table(misp_event, "Attribute") :
|
if is_safe_attribute_table(misp_event, "Attribute"):
|
||||||
flowables.append(PageBreak())
|
flowables.append(PageBreak())
|
||||||
|
|
||||||
event_attributes_title = Paragraph("Attributes", sample_style_sheet['Heading2'])
|
event_attributes_title = Paragraph("Attributes", sample_style_sheet['Heading2'])
|
||||||
|
@ -1601,7 +1730,7 @@ def collect_parts(misp_event, config=None):
|
||||||
flowables.append(event_attributes_title)
|
flowables.append(event_attributes_title)
|
||||||
flowables += table_direct_attributes
|
flowables += table_direct_attributes
|
||||||
|
|
||||||
if is_safe_attribute_table(misp_event, "Object") :
|
if is_safe_attribute_table(misp_event, "Object"):
|
||||||
flowables.append(PageBreak())
|
flowables.append(PageBreak())
|
||||||
|
|
||||||
event_objects_title = Paragraph("Objects", sample_style_sheet['Heading2'])
|
event_objects_title = Paragraph("Objects", sample_style_sheet['Heading2'])
|
||||||
|
@ -1647,6 +1776,10 @@ def convert_event_in_pdf_buffer(misp_event, config=None):
|
||||||
# Create a document buffer
|
# Create a document buffer
|
||||||
pdf_buffer = BytesIO()
|
pdf_buffer = BytesIO()
|
||||||
|
|
||||||
|
if is_in_config(config, 5): # We want internationalization
|
||||||
|
logger.info("Internationalization of fonts during pdf export activated. CJK-fonts supported.")
|
||||||
|
internationalize_font()
|
||||||
|
|
||||||
# DEBUG / TO DELETE : curr_document = SimpleDocTemplate('myfile.pdf')
|
# DEBUG / TO DELETE : curr_document = SimpleDocTemplate('myfile.pdf')
|
||||||
curr_document = SimpleDocTemplate(pdf_buffer,
|
curr_document = SimpleDocTemplate(pdf_buffer,
|
||||||
pagesize=PAGESIZE,
|
pagesize=PAGESIZE,
|
||||||
|
|
3
setup.py
3
setup.py
|
@ -59,5 +59,6 @@ setup(
|
||||||
'data/misp-objects/schema_objects.json',
|
'data/misp-objects/schema_objects.json',
|
||||||
'data/misp-objects/schema_relationships.json',
|
'data/misp-objects/schema_relationships.json',
|
||||||
'data/misp-objects/objects/*/definition.json',
|
'data/misp-objects/objects/*/definition.json',
|
||||||
'data/misp-objects/relationships/definition.json']},
|
'data/misp-objects/relationships/definition.json',
|
||||||
|
'tools/pdf_fonts/Noto_TTF/*']},
|
||||||
)
|
)
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -33,7 +33,7 @@ class TestMISPEvent(unittest.TestCase):
|
||||||
self.storage_folder = self.root + "reportlab_testoutputs/"
|
self.storage_folder = self.root + "reportlab_testoutputs/"
|
||||||
self.storage_image_folder = self.root + "reportlab_test_image_outputs/"
|
self.storage_image_folder = self.root + "reportlab_test_image_outputs/"
|
||||||
self.moduleconfig = ["MISP_base_url_for_dynamic_link", "MISP_name_for_metadata", "Activate_textual_description",
|
self.moduleconfig = ["MISP_base_url_for_dynamic_link", "MISP_name_for_metadata", "Activate_textual_description",
|
||||||
"Activate_galaxy_description"]
|
"Activate_galaxy_description", "Activate_related_events", "Activate_internationalization_fonts"]
|
||||||
|
|
||||||
|
|
||||||
def init_event(self):
|
def init_event(self):
|
||||||
|
@ -244,6 +244,58 @@ class TestMISPEvent(unittest.TestCase):
|
||||||
reportlab_generator.convert_event_in_pdf_buffer(self.mispevent, config),
|
reportlab_generator.convert_event_in_pdf_buffer(self.mispevent, config),
|
||||||
self.storage_folder + "galaxy_1.pdf")
|
self.storage_folder + "galaxy_1.pdf")
|
||||||
|
|
||||||
|
def test_related_events(self):
|
||||||
|
if self.check_python_2():
|
||||||
|
self.assertTrue(True)
|
||||||
|
else:
|
||||||
|
config = {}
|
||||||
|
config[self.moduleconfig[0]] = "http://localhost:8080"
|
||||||
|
config[self.moduleconfig[1]] = "My Wonderful CERT"
|
||||||
|
config[self.moduleconfig[2]] = True
|
||||||
|
config[self.moduleconfig[3]] = True
|
||||||
|
config[self.moduleconfig[4]] = True
|
||||||
|
|
||||||
|
self.init_event()
|
||||||
|
self.mispevent.load_file(self.test_folder + 'galaxy_1.json')
|
||||||
|
reportlab_generator.register_value_to_file(
|
||||||
|
reportlab_generator.convert_event_in_pdf_buffer(self.mispevent, config),
|
||||||
|
self.storage_folder + "related_events.pdf")
|
||||||
|
|
||||||
|
def test_related_events_too_simple(self):
|
||||||
|
if self.check_python_2():
|
||||||
|
self.assertTrue(True)
|
||||||
|
else:
|
||||||
|
config = {}
|
||||||
|
config[self.moduleconfig[0]] = "http://localhost:8080"
|
||||||
|
config[self.moduleconfig[1]] = "My Wonderful CERT"
|
||||||
|
config[self.moduleconfig[2]] = True
|
||||||
|
config[self.moduleconfig[3]] = True
|
||||||
|
config[self.moduleconfig[4]] = True
|
||||||
|
|
||||||
|
self.init_event()
|
||||||
|
self.mispevent.load_file(self.test_folder + 'to_delete1.json')
|
||||||
|
reportlab_generator.register_value_to_file(
|
||||||
|
reportlab_generator.convert_event_in_pdf_buffer(self.mispevent, config),
|
||||||
|
self.storage_folder + "related_events_no_related.pdf")
|
||||||
|
|
||||||
|
def test_utf(self):
|
||||||
|
if self.check_python_2():
|
||||||
|
self.assertTrue(True)
|
||||||
|
else:
|
||||||
|
config = {}
|
||||||
|
config[self.moduleconfig[0]] = "http://localhost:8080"
|
||||||
|
config[self.moduleconfig[1]] = "My Wonderful CERT"
|
||||||
|
config[self.moduleconfig[2]] = True
|
||||||
|
config[self.moduleconfig[3]] = True
|
||||||
|
config[self.moduleconfig[4]] = True
|
||||||
|
config[self.moduleconfig[5]] = True
|
||||||
|
|
||||||
|
self.init_event()
|
||||||
|
self.mispevent.load_file(self.test_folder + 'japanese_test.json')
|
||||||
|
reportlab_generator.register_value_to_file(
|
||||||
|
reportlab_generator.convert_event_in_pdf_buffer(self.mispevent, config),
|
||||||
|
self.storage_folder + "japanese_test.pdf")
|
||||||
|
|
||||||
def test_batch_image_events(self):
|
def test_batch_image_events(self):
|
||||||
# Test case ONLY for manual testing. Needs to download a full list of image events !
|
# Test case ONLY for manual testing. Needs to download a full list of image events !
|
||||||
|
|
||||||
|
@ -315,6 +367,8 @@ class TestMISPEvent(unittest.TestCase):
|
||||||
config[self.moduleconfig[1]] = "My Wonderful CERT"
|
config[self.moduleconfig[1]] = "My Wonderful CERT"
|
||||||
config[self.moduleconfig[2]] = True
|
config[self.moduleconfig[2]] = True
|
||||||
config[self.moduleconfig[3]] = True
|
config[self.moduleconfig[3]] = True
|
||||||
|
config[self.moduleconfig[4]] = True
|
||||||
|
config[self.moduleconfig[5]] = True
|
||||||
|
|
||||||
|
|
||||||
file_nb = str(len(os.listdir(self.test_batch_folder)))
|
file_nb = str(len(os.listdir(self.test_batch_folder)))
|
||||||
|
|
Loading…
Reference in New Issue