mirror of https://github.com/MISP/PyMISP
Merge pull request #362 from Vincent-CIRCL/master
fix: [exportpdf] Custom path for fonts and font packagepull/370/head
commit
637af49b21
Binary file not shown.
After Width: | Height: | Size: 337 KiB |
Binary file not shown.
After Width: | Height: | Size: 11 KiB |
Binary file not shown.
After Width: | Height: | Size: 10 KiB |
Binary file not shown.
After Width: | Height: | Size: 37 KiB |
|
@ -0,0 +1,46 @@
|
|||
## Overview
|
||||
|
||||
A big overview of the exportpdf tool is available at :
|
||||

|
||||
|
||||
## Parameters
|
||||
### Dynamic links
|
||||
You can specify your MISP URL to allow the PDF generator to create links from the PDF to your MISP instance events.
|
||||
The parameter to specify is "base_url_for_dynamic_link". Leave blank if you don't want the PDF generator to generate URL.
|
||||
### Name
|
||||
You can specify your organisation name, to be added to the PDF metadata.
|
||||
The parameter to specify is "name_for_metadata". Leave blank if you don't want the PDF generator to add this name to the metadata.
|
||||
### Textual description
|
||||
You can specify if you want a textual description of the event to be prepend to the generated PDF.
|
||||
The parameter to specify is "textual_description". Leave blank if you don't want the PDF generator to prepend this text description.
|
||||
### Galaxy description
|
||||
You can specify if you want related galaxies to be added to the PDF.
|
||||
The parameter to specify is "galaxy_description". Leave blank if you don't want the PDF generator to add galaxies description.
|
||||
### Related events
|
||||
You can specify if you want related events to be added to the PDF. Be aware this option might leads to information leaks if you have confidential events in your MISP instance.
|
||||
The parameter to specify is "related_events". Leave blank if you don't want the PDF generator to add related events..
|
||||
|
||||
Example of parameters all activated.
|
||||

|
||||
|
||||
|
||||
## International fonts
|
||||
If text of exported events does not show up in the final PDF, Fonts may be the source of the problem.
|
||||
For that, you can activate a international font, which handle CJK characters, named "Noto".
|
||||
|
||||
Due to their size, fonts are not bundled with PyMISP. You can download them, by following next steps :
|
||||
|
||||
Manual fonts install on a MISP instance, connected in SSH :
|
||||
> cd /usr/local/lib/python3.6/dist-packages/pymisp/tools/
|
||||
> git clone https://github.com/MISP/pdf_fonts
|
||||
|
||||
Then you can activate the option by filling the following parameter :
|
||||

|
||||
Leave blank if you don't want to use internationalization fonts.
|
||||
|
||||
If "Noto" is not fine for you (e.g. you want to use Arial Unicode[,](https://github.com/Vincent-CIRCL/Arial_Unicode) etc.) you can give as a parameter the font to use. Be sure the font is only contained in one TTF.
|
||||
|
||||
Fill this parameter, with the font's TTF's absolute path, as follow :
|
||||

|
||||
Note that if you give a custom fonts, bold/italic/special styles won't be used in the final PDF.
|
||||
Leave blank if you don't want to use your custom font.
|
|
@ -129,7 +129,8 @@ class Flowable_Tag(Flowable):
|
|||
|
||||
# Copy of pdfexport.py moduleconfig
|
||||
moduleconfig = ["MISP_base_url_for_dynamic_link", "MISP_name_for_metadata", "Activate_textual_description",
|
||||
"Activate_galaxy_description", "Activate_related_events", "Activate_internationalization_fonts"]
|
||||
"Activate_galaxy_description", "Activate_related_events", "Activate_internationalization_fonts",
|
||||
"Custom_fonts_path"]
|
||||
|
||||
# == Row colors of the table (alternating) ==
|
||||
EVEN_COLOR = colors.whitesmoke
|
||||
|
@ -217,6 +218,7 @@ SECOND_LEVEL_GALAXY_WIDTHS = ["20%", "80%"]
|
|||
CLUSTER_COLORS = [0] # or 1
|
||||
OFFSET = 1
|
||||
|
||||
|
||||
########################################################################
|
||||
# "UTILITIES" METHODS. Not meant to be used except for development purposes
|
||||
|
||||
|
@ -379,34 +381,48 @@ def general_style_generator():
|
|||
return lines_list
|
||||
|
||||
|
||||
def internationalize_font():
|
||||
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + "/tools"
|
||||
|
||||
def internationalize_font(config=None):
|
||||
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
|
||||
'''
|
||||
if is_in_config(config, 6) and config[moduleconfig[6]] != "" :
|
||||
# Handle custom fonts. Has to be TrueType = one TTF only
|
||||
fonts_path_custom = config[moduleconfig[6]]
|
||||
|
||||
noto_bold = BASE_DIR + "/pdf_fonts/Noto_TTF/NotoSansCJKtc-Bold.ttf"
|
||||
noto = BASE_DIR + "/pdf_fonts/Noto_TTF/NotoSansCJKtc-DemiLight.ttf"
|
||||
if fonts_path_custom and os.path.isfile(fonts_path_custom):
|
||||
registerFont(TTFont("custom_font", fonts_path_custom))
|
||||
FIRST_COL_FONT = 'custom_font'
|
||||
SECOND_COL_FONT = 'custom_font'
|
||||
|
||||
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 font, unable to access the file. Path : " + str(fonts_path_custom))
|
||||
else:
|
||||
logger.error(
|
||||
"Trying to load a custom (internationalization) font, unable to access the file : " + noto_bold)
|
||||
''' Handle provided NOTO fonts (CJK only for now)
|
||||
# Available fonts :
|
||||
NotoSansCJKtc - DemiLight.ttf
|
||||
NotoSansCJKtc - Regular.ttf
|
||||
NotoSansCJKtc - Black.ttf
|
||||
NotoSansCJKtc - Light.ttf
|
||||
NotoSansCJKtc - Thin.ttf
|
||||
NotoSansCJKtc - Bold.ttf
|
||||
NotoSansCJKtc - Medium.ttf
|
||||
'''
|
||||
font_path = os.path.join(os.path.abspath(os.path.dirname(sys.modules['pymisp'].__file__)), 'tools', 'pdf_fonts',
|
||||
'Noto_TTF')
|
||||
|
||||
noto_bold = font_path + "/NotoSansCJKtc-Bold.ttf"
|
||||
noto = font_path + "/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():
|
||||
|
@ -1227,8 +1243,8 @@ class Attributes():
|
|||
# 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":
|
||||
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"))
|
||||
|
||||
|
@ -1332,7 +1348,7 @@ class Sightings():
|
|||
list_sighting[1]) + "</font>"
|
||||
sight_text += " / " + "<font color =" + MISC_SIGHT_COLOR + "> Misc. : " + str(list_sighting[2]) + "</font>"
|
||||
|
||||
answer_sighting = self.value_formatter.get_unoverflowable_paragraph(sight_text)
|
||||
answer_sighting = self.value_formatter.get_unoverflowable_paragraph(sight_text, do_escape_string=False)
|
||||
else:
|
||||
# No tags for this object
|
||||
answer_sighting = self.value_formatter.get_unoverflowable_paragraph("No sighting")
|
||||
|
@ -1778,7 +1794,7 @@ def convert_event_in_pdf_buffer(misp_event, config=None):
|
|||
|
||||
if is_in_config(config, 5): # We want internationalization
|
||||
logger.info("Internationalization of fonts during pdf export activated. CJK-fonts supported.")
|
||||
internationalize_font()
|
||||
internationalize_font(config)
|
||||
|
||||
# DEBUG / TO DELETE : curr_document = SimpleDocTemplate('myfile.pdf')
|
||||
curr_document = SimpleDocTemplate(pdf_buffer,
|
||||
|
|
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_image_folder = self.root + "reportlab_test_image_outputs/"
|
||||
self.moduleconfig = ["MISP_base_url_for_dynamic_link", "MISP_name_for_metadata", "Activate_textual_description",
|
||||
"Activate_galaxy_description", "Activate_related_events", "Activate_internationalization_fonts"]
|
||||
"Activate_galaxy_description", "Activate_related_events", "Activate_internationalization_fonts", "Custom_fonts_path"]
|
||||
|
||||
|
||||
def init_event(self):
|
||||
|
@ -296,6 +296,45 @@ class TestMISPEvent(unittest.TestCase):
|
|||
reportlab_generator.convert_event_in_pdf_buffer(self.mispevent, config),
|
||||
self.storage_folder + "japanese_test.pdf")
|
||||
|
||||
def test_utf_heavy(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_heavy.json')
|
||||
reportlab_generator.register_value_to_file(
|
||||
reportlab_generator.convert_event_in_pdf_buffer(self.mispevent, config),
|
||||
self.storage_folder + "japanese_test_heavy.pdf")
|
||||
|
||||
def test_utf_ArialUNI_custompath(self):
|
||||
if self.check_python_2():
|
||||
self.assertTrue(True)
|
||||
elif not manual_testing:
|
||||
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
|
||||
config[self.moduleconfig[6]] = "/home/user/Desktop/PyMISP/pymisp/tools/pdf_fonts/arial-unicode-ms/ARIALUNI.TTF"
|
||||
|
||||
self.init_event()
|
||||
self.mispevent.load_file(self.test_folder + 'japanese_test_heavy.json')
|
||||
reportlab_generator.register_value_to_file(
|
||||
reportlab_generator.convert_event_in_pdf_buffer(self.mispevent, config),
|
||||
self.storage_folder + "custom_path.pdf")
|
||||
|
||||
def test_batch_image_events(self):
|
||||
# Test case ONLY for manual testing. Needs to download a full list of image events !
|
||||
|
||||
|
|
Loading…
Reference in New Issue