Ejemplo n.º 1
0
def pre_header(document, settings):
    # TODO: need to fix templates lr and kr, now they have different styles
    for i in range(6):
        if settings['type'] != 'LR':
            custom_header_style = document.styles['h{}'.format(i + 1)]

        # this code will be need in future when u will generate new template for kr
        else:
            custom_header_style = document.styles.add_style(
                'h{}'.format(i + 1), WD_STYLE_TYPE.PARAGRAPH)
            custom_header_style.font.rtl = True
            custom_header_style.font.name = settings[FORMAT][
                TYPE_OF_HEADER.format(i + 1)][FONT]
            custom_header_style.font.size = Pt(
                settings[FORMAT][TYPE_OF_HEADER.format(i + 1)][SIZE])
            custom_header_style.font.bold = True
            custom_header_style.font.italic = False
            custom_header_style.font.underline = False
            custom_header_style.font.color.rgb = RGBColor.from_string('000000')

            paragraph_format = custom_header_style.paragraph_format
            paragraph_format.alignment = WD_PARAGRAPH_ALIGNMENT.LEFT
            paragraph_format.space_after = Pt(STANDART_PT_HEADER)
            paragraph_format.left_indent = Cm(
                1.5)  # Inches(STANDART_INCHES + 0.1)

        custom_header_style.font.name = settings[FORMAT][TYPE_OF_HEADER.format(
            i + 1)][FONT]
        custom_header_style.font.size = Pt(
            settings[FORMAT][TYPE_OF_HEADER.format(i + 1)][SIZE])
Ejemplo n.º 2
0
    def add_title(self,
                  title,
                  font_size=12,
                  text_align='center',
                  color='000000',
                  left_indent=0.,
                  space_before=0.12,
                  space_after=0.12):

        h = self.document.add_heading(title, 1)
        h.paragraph_format.left_indent = Inches(left_indent)

        if text_align == 'center':
            h.paragraph_format.alignment = WD_ALIGN_PARAGRAPH.CENTER

        elif text_align == 'left':
            h.paragraph_format.alignment = WD_ALIGN_PARAGRAPH.LEFT

        if text_align == 'right':
            h.paragraph_format.alignment = WD_ALIGN_PARAGRAPH.RIGHT

        h.style.font.bold = True
        h.style.font.color.rgb = RGBColor.from_string(color)
        h.style.font.size = Pt(font_size)
        h.paragraph_format.space_before = Inches(space_before)
        h.paragraph_format.space_after = Inches(space_after)
Ejemplo n.º 3
0
 def _process_raw_document_content(self):
     author = self._document.add_paragraph(self._raw_metadata["author"])
     author.paragraph_format.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
     title = self._document.add_paragraph(self._raw_metadata["title"],
                                          self._document.styles["Title"])
     title.paragraph_format.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
     for line in self._raw_document_content:
         if line.startswith("# "):
             line = line.replace("# ", "")
             self._document.add_heading(line, level=1)
         elif line.startswith("András:") or line.startswith("Erika:"):
             name, line = line.split(": ")
             name += " üzenete:"
             self._document.add_paragraph(
                 name, style=self._document.styles["MSN Sender"])
             current_p = self._document.add_paragraph(
                 "", style=self._document.styles["MSN Message"])
             bullet = current_p.add_run("\u2022\u2000")
             bullet.font.color.rgb = RGBColor.from_string(self._grey)
             current_p.add_run(line)
         else:
             self._document.add_paragraph(
                 line, style=self._document.styles["Body"])
     year_p = self._document.add_paragraph()
     year_p.paragraph_format.space_before = Pt(11)
     year_p.paragraph_format.alignment = WD_PARAGRAPH_ALIGNMENT.RIGHT
     year = year_p.add_run(self._raw_metadata["rights"][-4:])
     year.font.italic = True
Ejemplo n.º 4
0
 def _generate_styles(self):
     normal = self._document.styles["Normal"]
     normal.font.name = "Times New Roman"
     body = self._document.styles.add_style("Body", WD_STYLE_TYPE.PARAGRAPH)
     body.base_style = self._document.styles["Normal"]
     body.font.size = Pt(12)
     body.paragraph_format.alignment = WD_PARAGRAPH_ALIGNMENT.JUSTIFY
     body.paragraph_format.first_line_indent = Mm(12.5)
     body.paragraph_format.space_after = Pt(0)
     body.paragraph_format.widow_control = True
     msn_message = self._document.styles.add_style("MSN Message",
                                                   WD_STYLE_TYPE.PARAGRAPH)
     msn_message.font.name = "Arial"
     msn_message.font.size = Pt(10)
     msn_message.base_style = self._document.styles["Body"]
     msn_message.paragraph_format.first_line_indent = Mm(0)
     msn_sender = self._document.styles.add_style("MSN Sender",
                                                  WD_STYLE_TYPE.PARAGRAPH)
     msn_sender.font.name = "Arial"
     msn_sender.font.size = Pt(10)
     msn_sender.base_style = self._document.styles["Body"]
     msn_sender.font.color.rgb = RGBColor.from_string(self._grey)
     msn_sender.paragraph_format.first_line_indent = Mm(0)
     msn_sender.paragraph_format.keep_with_next = True
     msn_sender.next_paragraph_style = msn_message
Ejemplo n.º 5
0
def add_style(doc, style_name, base_style, font_name, font_size, font_color):
    styles = doc.styles
    new_style = styles.add_style(style_name, WD_STYLE_TYPE.PARAGRAPH)
    new_style.base_style = styles[base_style]
    font = new_style.font
    font.name = font_name
    font.size = Pt(font_size)
    font.color.rgb = RGBColor.from_string(font_color)
Ejemplo n.º 6
0
    def __init__(self, **options):
        Formatter.__init__(self, **options)

        # create a dict of (start, end) tuples that wrap the
        # value of a token so that we can use it in the format
        # method later
        self.styles = {}

        # we iterate over the `_styles` attribute of a style item
        # that contains the parsed style values.
        for token, style in self.style:
            start = end = ''
            # a style item is a tuple in the following form:
            # colors are readily specified in hex: 'RRGGBB'
            if style['color'] == None:
                color = RGBColor.from_string("000000")
            else:
                color = RGBColor.from_string(style['color'])
            self.styles[token] = (color, style['bold'],
                                  style['italic'], style['underline'])
Ejemplo n.º 7
0
 def __changeFont(self, runsCollection, *, fontName, fontSize, fontType,
                  fontColor):
     if self.__isHexColor(fontColor):
         for run in runsCollection:
             font = run.font
             font.name = fontName
             font.bold, font.italic, font.underline = fontType
             font.color.rgb = RGBColor.from_string(fontColor[1:])
             font.size = Pt(fontSize)
     else:
         raise ValueError()
def helperHeading(doc, text, hexColor, font_name):
    styles = doc.styles
    new_heading_style = styles.add_style('New Heading{}'.format(text),
                                         WD_STYLE_TYPE.PARAGRAPH)
    new_heading_style.base_style = styles['Heading 1']
    font = new_heading_style.font
    font.name = font_name
    hex_tuple = RGBColor.from_string(hexColor)
    font.color.rgb = RGBColor(hex_tuple[0], hex_tuple[1], hex_tuple[2])
    #font.size = Pt(font_size)
    doc.add_paragraph(text, style='New Heading{}'.format(text))
def helperRun(paragraph, text, hexColor, underline, tab):
    run = paragraph.add_run(text)
    run.underline = bool(underline)
    font = run.font
    #font.size = Pt(font_size)
    hex_tuple = RGBColor.from_string(hexColor)
    font.color.rgb = RGBColor(hex_tuple[0], hex_tuple[1], hex_tuple[2])
    font.name = 'Athelas'
    if bool(tab) is True:
        paragraph.add_run().add_tab()
        paragraph.add_run().add_tab()
Ejemplo n.º 10
0
def apply_style(cell, style):
    styles = {
        # Color, Text Color, Bold?
        'Header': ('2F5496', 'FFFFFF', True),
        'Subheader': ('4B84E8', 'FFFFFF', False),
        'Subsubheader': ('BDBDBD', '000000', False)
    }
    assert style in styles
    c, tc, bold = styles[style]
    set_cell_color(cell, c)
    for p in cell.paragraphs:
        for r in p.runs:
            r.font.bold = bold
            r.font.color.rgb = RGBColor.from_string(tc)
Ejemplo n.º 11
0
def add_critical_practice_to_table_cells(results_doc):
    """Take the doc created via MailMerge, search for Critical Control
    mergefields and reposition/reformat them, then save the changes"""
    document = Document(results_doc)
    for table in document.tables:
        for column in table.columns:
            for cell in column.cells:
                for paragraph in cell.paragraphs:
                    note_regex = re.compile("Critical_Control")
                    if note_regex.search(paragraph.text):
                        paragraph.text = note_regex.sub('', paragraph.text)
                        para = cell.paragraphs[0].insert_paragraph_before()
                        paragraph_format = para.paragraph_format
                        paragraph_format.space_before = Pt(6)
                        new_critical_practice_line = para.add_run(
                            "Critical Control")
                        new_critical_practice_line.font.size = Pt(9)
                        new_critical_practice_line.bold = True
                        new_critical_practice_line.font.color.rgb = RGBColor.from_string(
                            'FF0000')
    document.save(results_doc)
Ejemplo n.º 12
0
def then_font_color_rgb_is_value(context, value):
    font = context.font
    expected_value = None if value == 'None' else RGBColor.from_string(value)
    assert font.color.rgb == expected_value
Ejemplo n.º 13
0
 def rgb_get_fixture(self, request):
     r_cxml, rgb = request.param
     color_format = ColorFormat(element(r_cxml))
     expected_value = None if rgb is None else RGBColor.from_string(rgb)
     return color_format, expected_value
Ejemplo n.º 14
0
 def add_font_color(self, hex_color_string=None):
     hex_color_string = hex_color_string or '#000000'
     if '#' in hex_color_string:
         hex_color_string = hex_color_string[1:]
     color = RGBColor.from_string(hex_color_string)
     self.ref.font.color.rgb = color
Ejemplo n.º 15
0
 def it_can_construct_from_a_hex_string_rgb_value(self):
     rgb = RGBColor.from_string('123456')
     assert rgb == RGBColor(0x12, 0x34, 0x56)
Ejemplo n.º 16
0
def edit_style(doc, style_name, font_name, font_size, font_color):
    style = doc.styles[style_name]
    font = style.font
    font.name = font_name
    font.size = Pt(font_size)
    font.color.rgb = RGBColor.from_string(font_color)
Ejemplo n.º 17
0
def write_docx(file_name, arrs, percentage=None):
    document = Document()
    document.styles['Normal'].font.name = u'微软雅黑'
    document.styles['Normal']._element.rPr.rFonts.set(qn('w:eastAsia'),
                                                      u'微软雅黑')
    p = document.add_paragraph('')
    if percentage:
        p.add_run('------------------统计---------------------\n')
        run = p.add_run('小学:' + str(percentage['primary'][0]) + '% -' +
                        str(percentage['primary'][1]) + '个\n')
        run.font.color.rgb = RGBColor.from_string('2F4F4F')
        run = p.add_run('初一:' + str(percentage['middle_one'][0]) + '% -' +
                        str(percentage['middle_one'][1]) + '个\n')
        run.font.color.rgb = RGBColor.from_string('000066')
        run = p.add_run('初二、初三:' + str(percentage['middle'][0]) + '% -' +
                        str(percentage['middle'][1]) + '个\n')
        run.font.color.rgb = RGBColor.from_string('4169E1')
        run = p.add_run('高中必修:' + str(percentage['must'][0]) + '% -' +
                        str(percentage['must'][1]) + '个\n')
        run.font.color.rgb = RGBColor.from_string('DAA520')
        run = p.add_run('高中选修:' + str(percentage['select'][0]) + '% -' +
                        str(percentage['select'][1]) + '个\n')
        run.font.color.rgb = RGBColor.from_string('3CB371')
        run = p.add_run('超纲:' + str(percentage['out'][0]) + '% -' +
                        str(percentage['out'][1]) + '个\n')
        run.font.color.rgb = RGBColor.from_string('FF4500')
        p.add_run('-----------------------------------------\n\n')
    for line in arrs:
        print(line)
        run = p.add_run(line[0])
        if line[1][0] == '#':
            run.font.color.rgb = RGBColor.from_string(line[1][1:])
        elif line[1] == 's':
            p.add_run(' ')
        elif line[1] == 'n':
            p.add_run('\n')

    p.add_run("\n=======  单词表 =======\n")
    p.add_run("\n小学单词 \n")
    for line in arrs:
        if line[1] == '#2F4F4F':
            if len(line[0]) > 2:
                run = p.add_run(line[0] + " \n")
    p.add_run("\n初中单词\n")
    for line in arrs:
        if line[1] == '#4169E1':
            if len(line[0]) > 2:
                run = p.add_run(line[0] + " \n")
    p.add_run("\n高中必修单词\n")
    for line in arrs:
        if line[1] == '#DAA520':
            if len(line[0]) > 2:
                run = p.add_run(line[0] + " \n")
    p.add_run("\n高中选修单词\n")
    for line in arrs:
        if line[1] == '#3CB371':
            if len(line[0]) > 2:
                run = p.add_run(line[0] + " \n")
    print(arrs)
    document.save(file_name)
    return file_name
Ejemplo n.º 18
0
def export_to_word(vuln_info, template, output_file='openvas_report.docx'):
    """
    Export vulnerabilities info in a Word file.

    :param vuln_info: Vulnerability list info
    :type vuln_info: list(Vulnerability)

    :param output_file: Filename of the Excel file
    :type output_file: str
    
    :param template: Path to Docx template
    :type template: str

    :raises: TypeError
    """

    import matplotlib.pyplot as plt
    import numpy as np
    import tempfile
    import os
    import math

    from docx import Document
    from docx.oxml.shared import qn, OxmlElement
    from docx.oxml.ns import nsdecls
    from docx.oxml import parse_xml
    from docx.shared import Cm, Pt, Twips
    from docx.enum.text import WD_ALIGN_PARAGRAPH, WD_LINE_SPACING
    from docx.enum.section import WD_ORIENT
    from docx.enum.style import WD_STYLE_TYPE
    from docx.enum.table import WD_ALIGN_VERTICAL
    from docx.shared import RGBColor

    if not isinstance(vuln_info, list):
        raise TypeError("Expected list, got '{}' instead".format(
            type(vuln_info)))
    else:
        for x in vuln_info:
            if not isinstance(x, Vulnerability):
                raise TypeError(
                    "Expected Vulnerability, got '{}' instead".format(type(x)))
    if not isinstance(output_file, str):
        raise TypeError("Expected str, got '{}' instead".format(
            type(output_file)))
    else:
        if not output_file:
            raise ValueError("output_file must have a valid name.")
    if template is not None:
        if not isinstance(template, str):
            raise TypeError("Expected str, got '{}' instead".format(
                type(template)))

    vuln_info, vuln_levels, vuln_host_by_level, vuln_by_family = _get_collections(
        vuln_info)

    # ====================
    # DOCUMENT PROPERTIES
    # ====================
    # Create new doc
    if template is None:
        document = Document()
        doc_section = document.sections[0]
        # Set A4 Format
        doc_section.page_width = Cm(21.0)
        doc_section.page_height = Cm(29.7)
        # Shrink margins almost to 0
        doc_section.left_margin = Cm(1.5)
        doc_section.right_margin = doc_section.left_margin
        doc_section.top_margin = Cm(1.0)
        doc_section.bottom_margin = Cm(1.0)
        # Force portrait
        doc_section.orientation = WD_ORIENT.PORTRAIT
    # use template
    else:
        document = Document(template)
        doc_section = document.sections[0]

    # Defining styles (if not defined already)
    # All used style will be custom, and with 'OR-' prefix.
    # In this way, the template can still define styles.
    doc_styles = document.styles

    # Base paragraph
    if 'OR-base' not in doc_styles:
        style_pr_base = doc_styles.add_style('OR-base',
                                             WD_STYLE_TYPE.PARAGRAPH)
        style_pr_base.font.name = 'Ubuntu'
        style_pr_base.font.size = Pt(8)
        style_pr_base.font.color.rgb = RGBColor.from_string('080808')
        style_pr_base.paragraph_format.left_indent = Cm(0)
        style_pr_base.paragraph_format.right_indent = Cm(0)
        style_pr_base.paragraph_format.first_line_indent = Cm(0)
        style_pr_base.paragraph_format.space_before = Cm(0)
        style_pr_base.paragraph_format.space_after = Cm(0)
        style_pr_base.paragraph_format.line_spacing_rule = WD_LINE_SPACING.SINGLE
        style_pr_base.paragraph_format.widow_control = True
        style_pr_base.paragraph_format.alignment = WD_ALIGN_PARAGRAPH.JUSTIFY_LOW
    # Base Styles modification
    if 'OR-base_bold' not in doc_styles:
        style_pr_body = doc_styles.add_style('OR-base_bold',
                                             WD_STYLE_TYPE.PARAGRAPH)
        style_pr_body.base_style = doc_styles['OR-base']
        style_pr_body.font.bold = True
    # Section headers
    if 'OR-Heading_base' not in doc_styles:
        style_pr_or_head_base = doc_styles.add_style('OR-Heading_base',
                                                     WD_STYLE_TYPE.PARAGRAPH)
        style_pr_or_head_base.base_style = doc_styles['OR-base_bold']
        style_pr_or_head_base.font.color.rgb = RGBColor.from_string('183868')
        style_pr_or_head_base.paragraph_format.space_after = Pt(4)
    # - Titles
    if 'OR-Title' not in doc_styles:
        style_pr_or_title = doc_styles.add_style('OR-Title',
                                                 WD_STYLE_TYPE.PARAGRAPH)
        style_pr_or_title.base_style = doc_styles['OR-Heading_base']
        style_pr_or_title.font.size = Pt(36)
        style_pr_or_title.paragraph_format.alignment = WD_ALIGN_PARAGRAPH.CENTER
        style_pr_or_head_base.paragraph_format.space_after = Pt(8)
    # - Headers
    if 'OR-Heading_1' not in doc_styles:
        style_pr_or_header = doc_styles.add_style('OR-Heading_1',
                                                  WD_STYLE_TYPE.PARAGRAPH)
        style_pr_or_header.base_style = doc_styles['OR-Heading_base']
        style_pr_or_header.font.size = Pt(20)
    if 'OR-Heading_2' not in doc_styles:
        style_pr_or_header = doc_styles.add_style('OR-Heading_2',
                                                  WD_STYLE_TYPE.PARAGRAPH)
        style_pr_or_header.base_style = doc_styles['OR-Heading_base']
        style_pr_or_header.font.size = Pt(16)
    if 'OR-Heading_3' not in doc_styles:
        style_pr_or_header = doc_styles.add_style('OR-Vuln_title',
                                                  WD_STYLE_TYPE.PARAGRAPH)
        style_pr_or_header.base_style = doc_styles['OR-Heading_base']
        style_pr_or_header.font.size = Pt(12)
    # - Vulnerabilities Titles
    for name, rgb in Config.colors().items():
        if 'OR-Vuln_title_' + name not in doc_styles:
            style_pr_or_header = doc_styles.add_style('OR-Vuln_title_' + name,
                                                      WD_STYLE_TYPE.PARAGRAPH)
            style_pr_or_header.base_style = doc_styles['OR-Vuln_title']
            style_pr_or_header.font.color.rgb = RGBColor.from_string(rgb[1:])
    # - Host with vulnerabilities title
    if 'OR-Vuln_hosts' not in doc_styles:
        style_pr_or_header = doc_styles.add_style('OR-Vuln_hosts',
                                                  WD_STYLE_TYPE.PARAGRAPH)
        style_pr_or_header.base_style = doc_styles['OR-Heading_base']
        style_pr_or_header.font.size = Pt(10)
    # TOC specific
    if 'OR-TOC_base' not in doc_styles:
        style_pr_or_toc_base = doc_styles.add_style('OR-TOC_base',
                                                    WD_STYLE_TYPE.PARAGRAPH)
        style_pr_or_toc_base.base_style = doc_styles['OR-base']
        style_pr_or_toc_base.font.color.rgb = RGBColor.from_string('183868')
    if 'OR-TOC_1' not in doc_styles:
        style_pr_or_toc = doc_styles.add_style('OR-TOC_1',
                                               WD_STYLE_TYPE.PARAGRAPH)
        style_pr_or_toc.base_style = doc_styles['OR-TOC_base']
        style_pr_or_toc.font.bold = True
    if 'OR-TOC_2' not in doc_styles:
        style_pr_or_toc = doc_styles.add_style('OR-TOC_2',
                                               WD_STYLE_TYPE.PARAGRAPH)
        style_pr_or_toc.base_style = doc_styles['OR-TOC_base']
    if 'OR-TOC_3' not in doc_styles:
        style_pr_or_toc = doc_styles.add_style('OR-Toc_3',
                                               WD_STYLE_TYPE.PARAGRAPH)
        style_pr_or_toc.base_style = doc_styles['OR-TOC_base']
    if 'OR-TOC_4' not in doc_styles:
        style_pr_or_toc = doc_styles.add_style('OR-TOC_4',
                                               WD_STYLE_TYPE.PARAGRAPH)
        style_pr_or_toc.base_style = doc_styles['OR-TOC_base']
        style_pr_or_toc.font.italic = True
    # Tables style
    # - Specific paragraph style to allow space before and after
    if 'OR-cell' not in doc_styles:
        style_pr_cell = doc_styles.add_style('OR-cell',
                                             WD_STYLE_TYPE.PARAGRAPH)
        style_pr_cell.base_style = doc_styles['OR-base']
        style_pr_cell.paragraph_format.space_before = Pt(1.5)
        style_pr_cell.paragraph_format.space_after = Pt(1.5)
    if 'OR-cell_bold' not in doc_styles:
        style_pr_cell = doc_styles.add_style('OR-cell_bold',
                                             WD_STYLE_TYPE.PARAGRAPH)
        style_pr_cell.base_style = doc_styles['OR-cell']
        style_pr_cell.font.bold = True

    # Clear all contents
    document._body.clear_content()

    # Set doc title
    doc_prop = document.core_properties
    doc_title = 'OpenVAS/GreenBone Report'
    doc_prop.title = doc_title
    doc_prop.category = "Report"

    # Effective writeable width
    # If margins set are float, try to fix (issue in python-docx: expected an int)
    # In this case, they _should be_ in twentieths of a point, so
    # multiply Twips helper
    try:
        doc_section.left_margin
    except ValueError as e:
        fixed_margin = float(re.search(": '(.+?)'", str(e)).group(1))
        doc_section.left_margin = Twips(fixed_margin)
    try:
        doc_section.right_margin
    except ValueError as e:
        fixed_margin = float(re.search(": '(.+?)'", str(e)).group(1))
        doc_section.right_margin = Twips(fixed_margin)

    page_width = doc_section.page_width - (doc_section.left_margin +
                                           doc_section.right_margin)

    ## Start actual document writing ##
    document.add_paragraph(doc_title, style='OR-Title')

    # ====================
    # TABLE OF CONTENTS
    # ====================
    # WARNING -Not working with LibreOffice
    document.add_paragraph('Table of Contents', style='OR-Heading_1')
    # keep the title as cover of the report
    document.add_page_break()

    par = document.add_paragraph(style='OR-base')
    run = par.add_run()
    fld_char = OxmlElement('w:fldChar')  # creates a new element
    fld_char.set(qn('w:fldCharType'), 'begin')  # sets attribute on element
    instr_text = OxmlElement('w:instrText')
    instr_text.set(qn('xml:space'), 'preserve')  # sets attribute on element
    instr_text.text = r'TOC \h \z \t "OR-TOC_1;1;OR-OR-TOC_1;2;OR-TOC_3;3;OR-TOC_4;3"'

    fld_char2 = OxmlElement('w:fldChar')
    fld_char2.set(qn('w:fldCharType'), 'separate')
    fld_char3 = OxmlElement('w:t')
    fld_char3.text = "# Right-click to update field. #"
    fld_char2.append(fld_char3)

    fld_char4 = OxmlElement('w:fldChar')
    fld_char4.set(qn('w:fldCharType'), 'end')

    r_element = run._r
    r_element.append(fld_char)
    r_element.append(instr_text)
    r_element.append(fld_char2)
    r_element.append(fld_char4)

    document.add_page_break()

    # ====================
    # MANAGEMENT SUMMARY
    # ====================
    document.add_paragraph('Management Summary', style='OR-Heading_1')
    document.add_paragraph('< TYPE YOUR MANAGEMENT SUMMARY HERE >',
                           style='OR-base')
    document.add_page_break()

    # ====================
    # TECHNICAL FINDINGS
    # ====================
    document.add_paragraph('Technical Findings', style='OR-Heading_1')
    document.add_paragraph(
        'The section below discusses the technical findings.', style='OR-base')

    # --------------------
    # SUMMARY TABLE
    # --------------------
    document.add_paragraph('Summary', style='OR-Heading_2')

    colors_sum = []
    labels_sum = []
    vuln_sum = []
    aff_sum = []

    table_summary = document.add_table(rows=1, cols=3)

    # TABLE HEADERS
    # --------------------
    hdr_cells = table_summary.rows[0].cells
    hdr_cells[0].paragraphs[0].add_run('Risk level')
    hdr_cells[1].paragraphs[0].add_run('Vulns number')
    hdr_cells[2].paragraphs[0].add_run('Affected hosts')
    # FIELDS
    # --------------------
    # Provide data to table and charts
    for level in Config.levels().values():
        row_cells = table_summary.add_row().cells
        row_cells[0].text = level.capitalize()
        row_cells[1].text = str(vuln_levels[level])
        row_cells[2].text = str(vuln_host_by_level[level])
        colors_sum.append(Config.colors()[level])
        labels_sum.append(level)
        vuln_sum.append(vuln_levels[level])
        aff_sum.append(vuln_host_by_level[level])

    # Apply styles
    # --------------------
    for h in hdr_cells:
        h.vertical_alignment = WD_ALIGN_VERTICAL.CENTER
        for p in h.paragraphs:
            p.style = doc_styles['OR-cell_bold']

    for r in table_summary.rows[1:]:
        for c in r.cells:
            c.vertical_alignment = WD_ALIGN_VERTICAL.CENTER
            for p in c.paragraphs:
                p.style = doc_styles['OR-cell']

    # --------------------
    # CHART
    # --------------------
    fd, path = tempfile.mkstemp(suffix='.png')
    chart_dpi = 144
    chart_height = Cm(8)
    par_chart = document.add_paragraph(style='OR-base')
    par_chart.alignment = WD_ALIGN_PARAGRAPH.CENTER
    run_chart = par_chart.add_run()

    bar_chart, bar_axis = plt.subplots(dpi=chart_dpi)
    bar_axis.set_title('Vulnerability summary by risk level', fontsize=10)

    pos = np.arange(len(labels_sum))
    width = 0.35

    bar_axis.set_xticks(pos)
    bar_axis.set_xticklabels(labels_sum)
    bar_chart.gca().spines['left'].set_visible(False)
    bar_chart.gca().spines['right'].set_visible(False)
    bar_chart.gca().spines['top'].set_visible(False)
    bar_chart.gca().spines['bottom'].set_position('zero')
    bar_axis.tick_params(top=False,
                         bottom=True,
                         left=False,
                         right=False,
                         labelleft=False,
                         labelbottom=True)
    bars_vuln = plt.bar(pos - width / 2,
                        vuln_sum,
                        width,
                        align='center',
                        label='Vulnerabilities',
                        color=colors_sum,
                        edgecolor='black')
    bars_aff = plt.bar(pos + width / 2,
                       aff_sum,
                       width,
                       align='center',
                       label='Affected hosts',
                       color=colors_sum,
                       edgecolor='black',
                       hatch='//')
    for barcontainer in (bars_vuln, bars_aff):
        for bar in barcontainer:
            height = bar.get_height()
            bar_chart.gca().text(bar.get_x() + bar.get_width() / 2,
                                 bar.get_height() + 0.3,
                                 str(int(height)),
                                 ha='center',
                                 color='black',
                                 fontsize=8)
    bar_chart.legend()

    bar_chart.savefig(path)

    # plt.show()  # DEBUG

    bar_height = chart_height
    run_chart.add_picture(path, height=bar_height)
    os.remove(path)

    pie_chart, pie_axis = plt.subplots(dpi=chart_dpi,
                                       subplot_kw=dict(aspect="equal"))
    pie_axis.set_title('Vulnerability by family', fontsize=10)

    values = list(vuln_by_family.values())
    pie, tx, autotexts = pie_axis.pie(values,
                                      labels=vuln_by_family.keys(),
                                      autopct='',
                                      textprops=dict(fontsize=8))
    for i, txt in enumerate(autotexts):
        txt.set_text('{}'.format(values[i]))
    pie_chart.savefig(path)

    # plt.show()  # DEBUG
    pie_height = chart_height
    run_chart.add_picture(path, height=pie_height)
    os.remove(path)

    # ====================
    # VULN PAGES
    # ====================
    cur_level = ""

    for i, vuln in enumerate(vuln_info, 1):
        # --------------------
        # GENERAL
        # --------------------
        level = vuln.level.lower()

        if level != cur_level:
            document.add_paragraph(
                level.capitalize(),
                style='OR-Heading_2').paragraph_format.page_break_before = True
            cur_level = level
        else:
            document.add_page_break()

        title = "[{}] {}".format(level.upper(), vuln.name)
        par = document.add_paragraph(title,
                                     style='OR-Vuln_title_' + vuln.level)

        table_vuln = document.add_table(rows=8, cols=3)
        table_vuln.autofit = False
        table_vuln.columns[0].width = Cm(0.35)
        table_vuln.columns[1].width = Cm(2.85)
        table_vuln.columns[-1].width = page_width
        for c in range(len(table_vuln.columns) - 1):
            table_vuln.columns[-1].width -= table_vuln.columns[c].width

        # COLOR
        # --------------------
        col_cells = table_vuln.columns[0].cells
        col_cells[0].merge(col_cells[7])
        color_fill = parse_xml(r'<w:shd {} w:fill="{}"/>'.format(
            nsdecls('w'),
            Config.colors()[vuln.level][1:]))
        col_cells[0]._tc.get_or_add_tcPr().append(color_fill)

        # TABLE HEADERS
        # --------------------
        hdr_cells = table_vuln.columns[1].cells
        hdr_cells[0].paragraphs[0].add_run('Description')
        hdr_cells[1].paragraphs[0].add_run('Impact')
        hdr_cells[2].paragraphs[0].add_run('Recommendation')
        hdr_cells[3].paragraphs[0].add_run('Details')
        hdr_cells[4].paragraphs[0].add_run('CVSS')
        hdr_cells[5].paragraphs[0].add_run('CVEs')
        hdr_cells[6].paragraphs[0].add_run('Family')
        hdr_cells[7].paragraphs[0].add_run('References')

        # FIELDS
        # --------------------
        cves = ", ".join(vuln.cves)
        cves = cves.upper() if cves != "" else "No CVE"

        cvss = str(vuln.cvss) if vuln.cvss != -1.0 else "No CVSS"

        txt_cells = table_vuln.columns[2].cells
        txt_cells[0].text = vuln.description
        txt_cells[1].text = vuln.impact
        txt_cells[2].text = vuln.solution
        txt_cells[3].text = vuln.insight
        txt_cells[4].text = cvss
        txt_cells[5].text = cves
        txt_cells[6].text = vuln.family
        txt_cells[7].text = vuln.references
        for c in txt_cells:
            for p in c.paragraphs:
                p.style = doc_styles['OR-cell']

        # Apply styles
        # --------------------
        for h in hdr_cells:
            for p in h.paragraphs:
                p.style = doc_styles['OR-cell_bold']

        for c in txt_cells:
            for p in c.paragraphs:
                p.style = doc_styles['OR-cell']

        # VULN HOSTS
        # --------------------
        document.add_paragraph('Vulnerable hosts', style='OR-Vuln_hosts')

        # add coloumn for result per port and resize columns
        table_hosts = document.add_table(cols=5, rows=(len(vuln.hosts) + 1))

        table_hosts.columns[0].width = Cm(2.8)
        table_hosts.columns[1].width = Cm(3.0)
        table_hosts.columns[2].width = Cm(2.0)
        table_hosts.columns[3].width = Cm(2.0)
        table_hosts.columns[-1].width = page_width
        for c in range(len(table_hosts.columns) - 1):
            table_hosts.columns[-1].width -= table_hosts.columns[c].width

        # TABLE HEADERS
        # --------------------
        hdr_cells = table_hosts.rows[0].cells
        hdr_cells[0].paragraphs[0].add_run('IP')
        hdr_cells[1].paragraphs[0].add_run('Host name')
        hdr_cells[2].paragraphs[0].add_run('Port number')
        hdr_cells[3].paragraphs[0].add_run('Port protocol')
        hdr_cells[4].paragraphs[0].add_run('Port result')
        # FIELDS
        # --------------------
        for j, (host, port) in enumerate(vuln.hosts, 1):
            cells = table_hosts.rows[j].cells
            cells[0].text = host.ip
            cells[1].text = host.host_name if host.host_name else "-"
            if port and port is not None:
                cells[2].text = "-" if port.number == 0 else str(port.number)
                cells[3].text = port.protocol
                cells[4].text = port.result
            else:
                cells[2].text = "No port info"

        # Apply styles
        # --------------------
        for h in hdr_cells:
            for p in h.paragraphs:
                p.style = doc_styles['OR-cell_bold']
        for r in table_hosts.rows[1:]:
            for c in r.cells:
                for p in c.paragraphs:
                    p.style = doc_styles['OR-cell']

    document.save(output_file)
Ejemplo n.º 19
0
def processData(dirname, sheet, domainList):
    '''
    第一部分:读取数据
    '''
    #读取
    for file in os.listdir(HTMLPATH + dirname):
        if file.endswith('html'):
            htmlFile = open(HTMLPATH + dirname + '/' + file, 'r')
            soup = BeautifulSoup(htmlFile, 'html.parser')
            htmlFile.close()
            break

    table_report_table = soup.find_all('table', class_='report_table')
    tr_even = table_report_table[0].find_all('tr', class_='even')

    #=================================================
    # 搜集内容:域名domain
    domain = tr_even[0].td.text.split('/')[2]

    # ================================================
    # 判断是哪种风险,找出为未知风险的报告
    risk = tr_even[1].td.text
    if risk == '未知风险':
        # 从excel中找到相应的域名
        flag = False
        i = 0
        for i in range(len(domainList)):
            if domainList[i].value == domain:
                flag = True
                break
        # 如果没找到,则报错并返回
        if flag == False:
            print(domain + ':汇总表中未找到')
            return 0
        #找到的,则在对应的备注栏填写'站点不可达'
        sheet.cell(i + 3, 11, '站点不可达')
        return 0
    #================================================
    #搜集内容:时间timeStatistics[]
    for tr in tr_even:
        if tr.find('th', text='时间统计') != None:
            timeStatistics = tr.td.text.split('\n')[1:4]
            timeStatistics[0] = timeStatistics[0].strip()[3:22]  #timeStart
            timeStatistics[1] = timeStatistics[1].strip()[3:22]  #timeStop
            timeStatistics[2] = timeStatistics[2].strip()[3:]  #timeConsume
            break

    #================================================
    #搜集内容:高中低漏洞数distribut[],漏洞总数sum_all
    sum_all = 0
    distribut = tr_even[2].td.text.split('\n')[1:4]
    for i in range(len(distribut)):
        distribut[i] = int(distribut[i].strip()[4:-2])
        sum_all += distribut[i]
    #================================================
    #搜集内容:检测结果result[],result里面每个元素都是列表,包含4个元素
    table_tmp = []
    result = []
    for table in table_report_table:
        if table.find('th', text='漏洞名称') != None:
            table_tmp.append(table)
    table = table_tmp[-1].find_all('tr')[1:]
    for tr in table:
        td = tr.find_all('td')
        tdClass = td[0].attrs['class']  #这里tdClass是list格式,虽然这里只有1个元素
        if tdClass[0] == 'vul-vh':
            result.append([
                td[0].text.split('\n')[2].strip(), td[1].text.strip(), '高危',
                'EB3323'
            ])
        elif tdClass[0] == 'vul-vm':
            result.append([
                td[0].text.split('\n')[2].strip(), td[1].text.strip(), '中危',
                'F6C143'
            ])
        else:
            result.append([
                td[0].text.split('\n')[2].strip(), td[1].text.strip(), '低危',
                '4EAC5B'
            ])
    '''
    第二部分:写到word和excel中
    '''
    #从excel中找到相应的域名
    flag = False
    i = 0
    for i in range(len(domainList)):
        if domainList[i].value == domain:
            flag = True
            break
    #如果没找到,则报错并返回
    if flag == False:
        print(domain + ':汇总表中未找到')
        return 0

    # 获取当前年月日
    timeStr = time.strftime('%Y%m%d', time.localtime())
    #设置文件名
    wordFileName = '006' + timeStr + str(i + 1).zfill(5) + 'a.docx'
    wordFileName_Pdf = '006' + timeStr + str(i + 1).zfill(5) + 'a.pdf'
    pdfFileName = '006' + timeStr + str(i + 1).zfill(5) + 'ad.pdf'
    wordFilePath = WORDPATH + wordFileName
    # 写入excel
    for j in range(len(distribut)):
        #distribut里放的是数字形式,如果为string,则excel里面也会算文字
        sheet.cell(i + 3, j + 3, distribut[j])
    sheet.cell(i + 3, j + 4, timeStatistics[0])
    sheet.cell(i + 3, j + 5, wordFileName_Pdf)
    #从模板word复制到WORDPATH下
    os.system('cp ' + templateFilePath + ' ' + wordFilePath)
    wordFile = Document(wordFilePath)
    tables = wordFile.tables
    #第一个表所有和第二个表的时间
    ##域名
    run = tables[0].cell(0, 1).paragraphs[0].add_run(domain)
    run.font.size = Pt(16)
    run.font.bold = 1
    ##时间
    for i in range(len(timeStatistics)):
        #1表
        run = tables[0].cell(i + 1, 1).paragraphs[0].add_run(timeStatistics[i])
        run.font.size = Pt(16)
        run.font.bold = 1
        #2表
        run = tables[1].cell(i + 3, 1).paragraphs[0].add_run(timeStatistics[i])
        run.font.size = Pt(11)
    #第二个表剩余的内容
    ##域名
    run = tables[1].cell(0, 1).paragraphs[0].add_run(domain)
    run.font.size = Pt(11)
    ##漏洞数
    run = tables[1].cell(1, 1).paragraphs[0].add_run(str(distribut[0]))
    run.font.size = Pt(11)
    run = tables[1].cell(1, 3).paragraphs[0].add_run(str(distribut[1]))
    run.font.size = Pt(11)
    run = tables[1].cell(2, 1).paragraphs[0].add_run(str(distribut[2]))
    run.font.size = Pt(11)
    run = tables[1].cell(2, 3).paragraphs[0].add_run(str(sum_all))
    run.font.size = Pt(11)
    #第三个表
    for i in range(len(result)):
        new_cells = tables[2].add_row().cells
        #序号
        run = new_cells[0].paragraphs[0].add_run(str(i + 1))
        run.font.size = Pt(11)
        run.font.bold = 1
        new_cells[0].paragraphs[0].alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
        #检测问题
        run = new_cells[1].paragraphs[0].add_run(result[i][0])
        run.font.size = Pt(11)
        #漏洞数
        run = new_cells[2].paragraphs[0].add_run(result[i][1])
        run.font.size = Pt(11)
        new_cells[2].paragraphs[0].alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
        #风险程度
        run = new_cells[3].paragraphs[0].add_run(result[i][2])
        run.font.size = Pt(11)
        run.font.bold = 1
        run.font.color.rgb = RGBColor.from_string(result[i][3])
        new_cells[3].paragraphs[0].alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
    #保存文档
    wordFile.save(wordFilePath)
    '''
    重命名pdf
    '''
    os.system('cp ' + PDFPATH + dirname + '/http_' + domain + '.pdf ' +
              PDFOUTPUTPATH + pdfFileName)
    return 0
Ejemplo n.º 20
0
def when_I_assign_value_to_font_color_rgb(context, value):
    font = context.font
    new_value = None if value == 'None' else RGBColor.from_string(value)
    font.color.rgb = new_value
Ejemplo n.º 21
0
def writeTable(sctPars, filename, obstime):
    """
    Write *.docx and *.tex tables to insert in the flight description.
    """
    import re
    import os
    from docx import Document
    from docx.shared import Inches
    from docx.shared import Cm
    from docx.shared import Pt
    from docx.shared import RGBColor
    from astropy import units as u
    from astropy.coordinates import SkyCoord

    # Check mode
    if sctPars['INSTMODE'] in ['SYMMETRIC_CHOP', 'TOTAL_POWER']:
        pass
    else:
        print(
            'Table cannot be yet saved in this mode. Wait for future implementations !'
        )
        return

    lines = {
        51.814: '[OIII]',
        54.311: '[FeI]',
        56.311: '[SI]',
        57.317: '[NIII]',
        60.640: '[PII]',
        63.184: '[OI]',
        67.200: '[FII]',
        68.473: '[SiI]',
        87.384: '[FeII]',
        88.356: '[OIII]',
        89.237: '[AlI]',
        105.370: '[FeIII]',
        111.183: '[FeI]',
        121.898: '[NII]',
        129.682: '[SiI]',
        145.525: '[OI]',
        157.741: '[CII]',
        177.431: '[CIII]',
        205.178: '[NII]'
    }

    blue = sctPars["BLUE_MICRON"]
    red = sctPars["RED_MICRON"]
    wb = float(blue)
    wr = float(red)
    blueline = '?'
    redline = '?'
    for key in lines.keys():
        if np.abs(wb - key) < 0.01:
            blueline = ' ' + lines[key]
        if np.abs(wr - key) < 0.01:
            redline = ' ' + lines[key]

    # Look for readme file
    aor_label = re.findall(r"act(\d+)", filename)[0]
    aorfile = 'act' + aor_label + '.readme'
    if os.path.exists(aorfile):
        with open(aorfile) as f:
            content = f.read().splitlines()
        if len(content) == 1:
            time_planned = content[0]
            comments = 'Comments: None'
        elif len(content) == 2:
            time_planned = content[0] + ' m'
            comments = content[1]
        else:
            print(
                'The readme file has too many lines.\n First line is time, second (optional) comments.'
            )
            time_planned = ' ? m'
            comments = 'Comments: None'
    else:
        print('There is no readme file with time planned (and comments).')
        time_planned = ' ? m'
        comments = 'Comments: None'

    document = Document()
    # Change font, size, and color
    run = document.add_paragraph().add_run('Observations')
    font = run.font
    font.bold = True
    font.name = 'Calibri'
    font.size = Pt(12)
    font.color.rgb = RGBColor.from_string('002a77')

    table = document.add_table(rows=6, cols=6)

    # Fix width of cells
    for cell in table.columns[0].cells:
        cell.width = Cm(2)
    for cell in table.columns[1].cells:
        cell.width = Cm(4)
    for cell in table.columns[2].cells:
        cell.width = Cm(5)
    for cell in table.columns[3].cells:
        cell.width = Cm(4)
    for cell in table.columns[4].cells:
        cell.width = Cm(4)
    for cell in table.columns[5].cells:
        cell.width = Cm(4)

    row1 = table.rows[0]
    act = row1.cells[0]
    act.text = 'Act\n' + aor_label
    for paragraph in act.paragraphs:
        for run in paragraph.runs:
            run.font.bold = True
    target = row1.cells[1].merge(row1.cells[2])
    target.text = 'Target\n' + sctPars["TARGET_NAME"]
    row1.cells[3].text = 'AOR\n' + sctPars["AORID"]
    coords = row1.cells[4].merge(row1.cells[5])
    coords.text = 'R.A.: ' + sctPars["TARGET_LAMBDA"] + '\nDec:' + sctPars[
        "TARGET_BETA"]
    row2 = table.rows[1]
    redshift = table.cell(1, 0).merge(table.cell(1, 2))
    c = 299792.458
    cz = '{0:.1f}'.format(float(sctPars["REDSHIFT"]) * c)
    redshift.text = 'Redshift: ' + cz + ' km/s'
    redshift.text += '\n                                   Rest Wavelength:'
    redshift.text += '\n                                     Grating steps:'
    redshift.text += '\n                      Grating positions per nod:'
    nodcycles = sctPars['NODCYCLES']
    ngratpos = sctPars['BLUE_POSUP']  # hypothesis of posup only
    gratstep = sctPars['BLUE_SIZEUP']
    ngratnod = str(int(ngratpos) // int(nodcycles))

    row2.cells[3].text = 'Blue grating\n' + blue + '\u00b5m' + blueline
    row2.cells[
        3].text += '\n' + ngratpos + ' \u00d7 ' + gratstep + '\n' + ngratnod
    redgrating = table.cell(1, 4).merge(table.cell(1, 5))
    redgrating.text = 'Red grating\n' + red + '\u00b5m' + redline
    redgrating.text += '\n' + ngratpos + ' \u00d7 ' + gratstep + '\n' + ngratnod

    dichroic = table.cell(2, 0).merge(table.cell(2, 1))
    dichroic.text = 'Dichroic: ' + sctPars["DICHROIC"]
    table.cell(2, 2).text = 'Blue order: M' + sctPars["ORDER"]
    gratingmode = table.cell(2, 3).merge(table.cell(2, 5))
    gratingmode.text = 'Grating mode: ' + sctPars['BLUE_LAMBDA']

    # Case of symmetric chop
    if sctPars['INSTMODE'] == 'SYMMETRIC_CHOP':
        # Chopping part
        mode = table.cell(3, 0).merge(table.cell(3, 1))
        mode.text = 'Mode:\n' + sctPars['OBSMODE'] + ' ' + sctPars['NODPATTERN']
        table.cell(3, 2).text = 'Chop throw:\n' + sctPars['CHOP_AMP'] + '"'
        table.cell(
            3,
            3).text = 'Chop angle:\n' + sctPars['CHOP_POSANG'] + '\u00b0 J2000'
        table.cell(3, 4).text = 'Primary array: ' + sctPars['PRIMARYARRAY']
        table.cell(
            3, 5).text = 'FOV angle:\n' + sctPars['DETANGLE'] + '\u00b0 J2000'
    elif sctPars['INSTMODE'] == 'TOTAL_POWER':
        mode = table.cell(3, 0).merge(table.cell(3, 1))
        mode.text = 'Mode:\n' + sctPars['INSTMODE'] + ' ' + sctPars[
            'NODPATTERN']
        table.cell(3, 2).text = 'Off mode:\n' + sctPars['OFFPOS']
        #ra = float(sctPars['OFFPOS_LAMBDA']) Wrong ! This is not the position
        #dec = float(sctPars['OFFPOS_BETA'])
        #c = SkyCoord(ra=ra*u.degree, dec=dec*u.degree, frame='icrs')
        #sra, sdec = c.to_string('hmsdms').split(' ')
        table.cell(3, 3).text = 'Offset:\n' + sctPars[
            'OFFPOS_LAMBDA'] + '\n' + sctPars['OFFPOS_BETA']
        table.cell(3, 4).text = 'Primary array: ' + sctPars['PRIMARYARRAY']
        table.cell(
            3, 5).text = 'FOV angle:\n' + sctPars['DETANGLE'] + '\u00b0 J2000'

    dithering = table.cell(4, 0).merge(table.cell(4, 1))
    dithering.text = 'Map: ' + sctPars['DITHMAP_NUMPOINTS'] + ' point dither'
    timeplanned = table.cell(4, 2).merge(table.cell(4, 3))
    timeplanned.text = 'Time planned: ' + time_planned
    timerunning = table.cell(4, 4).merge(table.cell(4, 5))
    obstime = '{0:.1f} m'.format(float(obstime) / 60)
    timerunning.text = 'Time running: ' + obstime
    comment = table.cell(5, 0).merge(table.cell(5, 5))
    comment.text = comments
    table.style = 'Table Grid'
    table.allow_autofit = True
    # Change font, size, and color
    for row in table.rows:
        for cell in row.cells:
            paragraphs = cell.paragraphs
            for paragraph in paragraphs:
                for run in paragraph.runs:
                    font = run.font
                    font.name = 'Calibri'
                    font.size = Pt(12)
                    #font.color.rgb = RGBColor(0x3f, 0x2c, 0x36)
                    font.color.rgb = RGBColor.from_string('002a77')
    # Save file
    #filename = filename[:-4]+'.docx'
    document.save(filename)

    # Latex format table for future flight descriptions in Latex
    filename = filename[:-5] + '.tex'
    with open(filename, 'w') as f:
        f.write(r'%\documentclass{article}' + '\n')
        f.write(r'%\begin{document}' + '\n')
        f.write(r'\begin{table}' + '\n' + r'\centering' + '\n')
        f.write(r'\begin{tabular}{llll}' + '\n')
        f.write(r'\hline' + '\n')
        f.write(r'\hline' + '\n')
        f.write(r'\multicolumn{2}{l}{\bf Act ' + aor_label +
                '}&{\sl AOR ID:}   ' + sctPars["AORID"].replace('_', '\_') +
                '&{\sl P.I.:} ' + sctPars["OBSERVER"] + r'\\' + '\n')
        f.write(r'\multicolumn{2}{l}{' +
                sctPars["TARGET_NAME"].replace('_', '\_') + '}& ' +
                sctPars["TARGET_LAMBDA"].replace(' ', ':') + ' ' +
                sctPars["TARGET_BETA"].replace(' ', ':') + '& ' + cz +
                r' km/s\\' + '\n')
        f.write(r'\hline' + '\n')
        f.write(r'\hline' + '\n')
        f.write(r'\multicolumn{2}{l}{\sl Grating} & Blue & Red\\' + '\n')
        f.write(r'\hline' + '\n')
        f.write(r'\multicolumn{2}{l}{\sl Reference Wavelength:} & ' + blue +
                r'$\mu$m' + blueline + ' &' + red + r'$\mu$m' + redline +
                r'\\' + '\n')
        f.write(r'\multicolumn{2}{l}{\sl Grating Steps:} & ' + ngratpos +
                r' $\times$ ' + gratstep + '& ' + ngratpos + r' $\times$ ' +
                gratstep + r'\\' + '\n')
        f.write(r'\multicolumn{2}{l}{\sl Grating Steps per Nod:} &' +
                ngratnod + '&' + ngratnod + r'\\' + '\n')
        f.write(
            r'\multicolumn{2}{l}{\sl Grating mode: }&  \multicolumn{2}{l}{' +
            sctPars['BLUE_LAMBDA'] + r'}\\' + '\n')
        f.write(r'\hline' + '\n')
        f.write(r'\hline' + '\n')
        f.write('{\sl Dichroic: } ' + sctPars["DICHROIC"] +
                '&{\sl Blue order: } M' + sctPars["ORDER"] +
                '&{\sl Primary array: } ' + sctPars['PRIMARYARRAY'] +
                '&{\sl FOV angle: } ' + sctPars['DETANGLE'] + r'$^o$ J2000' +
                r'\\' + '\n')
        f.write(r'\hline' + '\n')
        f.write(r'\hline' + '\n')
        if sctPars['INSTMODE'] == 'SYMMETRIC_CHOP':
            f.write(r'{\sl Chop}&{\sl Mode}&{\sl Throw}&{\sl Angle}\\' + '\n')
            f.write(r'\hline' + '\n')
            f.write('&' + sctPars['OBSMODE'] + ' ' + sctPars['NODPATTERN'] +
                    '&' + sctPars['CHOP_AMP'] + r'"' + '&' +
                    sctPars['CHOP_POSANG'] + '$^o$ J2000' + r'\\' + '\n')
        else:
            f.write(
                r'{\sl Mode}&{\sl Nod pattern}&{\sl Offset}&{\sl Coords}\\' +
                '\n')
            f.write(r'\hline' + '\n')
            f.write(sctPars['INSTMODE'] + ' &' + sctPars['NODPATTERN'] + '&' +
                    sctPars['OFFPOS'] +
                    #'&'+ sra +' '+sdec+r'\\'+'\n')
                    '&' + sctPars['OFFPOS_LAMBDA'] + ' ' +
                    sctPars['OFFPOS_BETA'] + r'\\' + '\n')

        f.write(r'\hline' + '\n')
        f.write(r'\hline' + '\n')
        f.write(r'\multicolumn{2}{l}{{\sl Map}: ' +
                sctPars['DITHMAP_NUMPOINTS'] + ' point dither}' +
                r'&{\sl Time planned: } ' + time_planned +
                r'&{\sl Time running: } ' + obstime + r'\\' + '\n')
        f.write(r'\hline' + '\n')
        f.write(r'\hline' + '\n')
        f.write(r'\multicolumn{4}{l}{' + comments + r'}\\' + '\n')
        f.write(r'\hline' + '\n')
        f.write(r'\hline' + '\n')
        f.write(r'\end{tabular}' + '\n')
        f.write(r'\end{table}' + '\n')
        f.write(r'%\end{document}')
Ejemplo n.º 22
0
def get_para_object(count, label, body, word_list, par, name):
    run = par.add_run("{}, Label: {}".format(count, str(label)))
    run.font.size = Pt(7)
    run.font.bold = True
    run.font.underline = True
    run.font.all_caps = True
    # run.font.outline = True
    if label >= 4:
        # run.font.highlight_color = WD_COLOR_INDEX.RED
        run.font.color.rgb = RGBColor.from_string('FF0000')
    elif label == 3:
        # run.font.highlight_color = WD_COLOR_INDEX.YELLOW
        run.font.color.rgb = RGBColor.from_string('808000')
    elif label < 3:
        # run.font.highlight_color = WD_COLOR_INDEX.BRIGHT_GREEN
        run.font.color.rgb = RGBColor.from_string('6897BB')
    run.add_break(WD_BREAK.LINE)
    body = ' '.join(body.split())
    if type(name) != type(' '):
        names = []
    else:
        names = name.split(";")
    # print (names)
    for word in word_list:
        f = word.split()[0]
        s = word.split()[1]
        if len(f) <= 3 and len(s) <= 3:
            word_list.remove(word)
    h_body = get_highlighted_body(body, word_list)
    h_body = unify_phrases(h_body)

    # print (h_body)
    r = re.compile('HSTART_')
    fragments = r.split(h_body)
    # par = doc.add_paragraph()
    second = fragments[0]
    done = False
    for n in names:
        if n in second:
            name_ind = second.lower().index(n.lower())
            run = par.add_run(second[:name_ind])
            run.font.size = Pt(6)
            run = par.add_run(second[name_ind:name_ind + len(n)])
            run.font.size = Pt(9)
            run.font.italic = True
            run.font.underline = True
            run = par.add_run(second[name_ind + len(n):])
            run.font.size = Pt(6)
            done = True
            break
    if not done:
        run = par.add_run(fragments[0])
        run.font.size = Pt(6)

    # run.font.size = Pt(6)
    for ind, f in enumerate(fragments[1:]):
        first = f.split('HEND')[0]
        second = f.split('HEND')[1]
        # count = int(first[0])
        count = int(first[0])
        first = first[1:]

        run = par.add_run(first)
        font_map_obj = FONT_MAP[count]
        run.font.size = Pt(8)
        run.font.highlight_color = font_map_obj['highlight']
        run.font.color.rgb = font_map_obj['color']
        done = False
        if second:
            for n in names:
                if n in second:
                    name_ind = second.lower().index(n.lower())
                    run = par.add_run(second[:name_ind])
                    run.font.size = Pt(6)
                    run = par.add_run(second[name_ind:name_ind + len(n)])
                    run.font.size = Pt(9)
                    run.font.italic = True
                    run.font.underline = True
                    run = par.add_run(second[name_ind + len(n):])
                    run.font.size = Pt(6)
                    done = True
                    break
            if not done:
                run = par.add_run(second)
                run.font.size = Pt(6)

    return par
Ejemplo n.º 23
0
section = doc3.sections[0]
new_width, new_height = section.page_height, section.page_width
section.orientation = WD_ORIENT.LANDSCAPE
section.page_width = new_width
section.page_height = new_height
# 2 - blue, 4 - bright green, 5 - dark_blue, 6 - dark red, 7 - dark yellow
# 8 - gray, 10 - green, 11 -pink, 12 - red, 13- teal, 14- turquoise, 15- violet

#141414 - black, FF0000 - red, F3FF69 - yellow, FFACB7 - pink, 808000- mehendi, 6897BB - blue

FONT_MAP = {
    0: {
        'size': Pt(10),
        'highlight': WD_COLOR_INDEX.BRIGHT_GREEN,
        'color': RGBColor.from_string('141414')
    },
    1: {
        'size': Pt(10),
        'highlight': WD_COLOR_INDEX.PINK,
        'color': RGBColor.from_string('141414')
    },
    2: {
        'size': Pt(10),
        'highlight': WD_COLOR_INDEX.RED,
        'color': RGBColor.from_string('141414')
    },
    3: {
        'size': Pt(10),
        'highlight': WD_COLOR_INDEX.TURQUOISE,
        'color': RGBColor.from_string('141414')
Ejemplo n.º 24
0
# font.size = Pt(36)

# Each Document object provides access to its CoreProperties object via its core_properties attribute.
# About CoreProperties objects: https://python-docx.readthedocs.org/en/latest/api/document.html#id1
document.core_properties.author = 'author'
document.core_properties.comments = 'comments'

# document.add_heading('Document Title', 0)
p = document.add_paragraph('A plain paragraph having some ')
p.add_run('bold').bold = True
p.add_run(' and some ')
p.add_run('italic.').italic = True

# About RGBColor objects: https://python-docx.readthedocs.org/en/latest/api/shared.html#rgbcolor-objects
p.add_run('\n天蓝色').font.color.rgb = RGBColor(0x87, 0xCE, 0xEB) # 天蓝色
p.add_run('WHITE').font.color.rgb = RGBColor.from_string('FFFFFF') # white
p.add_run('RED').font.color.rgb = RGBColor.from_string('FF0000') # red
p.add_run('BLUE').font.color.rgb = RGBColor.from_string('0000FF') # blue
p.add_run('BLACK').font.color.rgb = RGBColor.from_string('000000') # black
# 紫色:800080    天蓝色:87CEEB    黄色:FFFF00
# 白色: FFFFFF    红色: FF0000    蓝色: 0000FF    黑色: 000000
# More: http://www.360doc.com/content/12/0219/22/19147_187921920.shtml

# add pic, original size
picname = 'pic.png'
if os.path.exists(picname):
    p.add_run('\nCode: ').font.color.rgb = RGBColor.from_string('0000FF') # blue
    # See: http://stackoverflow.com/questions/26617218/python-docx-add-picture-size-wont-print-as-shown-on-screen
    # document.add_picture('pic.png', width=Inches(4.9))
    im = Image.open(picname)
    width, height = im.size
Ejemplo n.º 25
0
def then_font_color_rgb_is_value(context, value):
    font = context.font
    expected_value = None if value == 'None' else RGBColor.from_string(value)
    assert font.color.rgb == expected_value
Ejemplo n.º 26
0
def when_I_assign_value_to_font_color_rgb(context, value):
    font = context.font
    new_value = None if value == 'None' else RGBColor.from_string(value)
    font.color.rgb = new_value
Ejemplo n.º 27
0
 def it_can_construct_from_a_hex_string_rgb_value(self):
     rgb = RGBColor.from_string('123456')
     assert rgb == RGBColor(0x12, 0x34, 0x56)
Ejemplo n.º 28
0
def generate_report_or_attachments(mission_id, zip_attachments=False):
    '''
    Generates the report docx or attachments zip.
    :param mission_id: The id of the mission
    :param zip_attachments: True to return a zip of attachments, False to get the docx report as an IOStream
    :return: Returns StringIO if returning a report, a zip object otherwise
    '''
    system_classification = DARTDynamicSettings.objects.get_as_object(
    ).system_classification
    system_classification_verbose = system_classification.verbose_legend
    system_classification_short = system_classification.short_legend

    mission = Mission.objects.get(id=mission_id)
    tests = TestSortingHelper.get_ordered_testdetails(
        mission_id=mission_id, reportable_tests_only=True)

    # Set some values we'll use throughout this section
    total_reportable_tests = len(tests)
    total_tests_with_findings = TestDetail.objects.filter(
        mission=mission, has_findings=True).count()
    total_tests_without_findings = TestDetail.objects.filter(
        mission=mission, has_findings=False).count()
    LIGHTEST_PERMISSIBLE_CLASSIFICATION_LABEL_COLOR = 0xbbbbbb
    DARKEN_OVERLY_LIGHT_CLASSIFICATION_LABEL_COLOR_BY = 0x444444
    mission_data_dir = None
    report_has_attachments = False

    def replace_document_slugs(doc):
        """Cycle through the runs in each paragraph in the template & replace handlebar slugs"""

        logger.debug('> replace_document_slugs')

        handlebar_slugs = {
            r'{{AREA}}': str(mission.business_area),
            r'{{MISSION}}': str(mission.mission_name),
            r'{{GENERATION_DATE}}': now().strftime('%x'),
            r'{{TOTAL_TESTS}}': str(total_reportable_tests),
            r'{{TESTS_WITH_FINDINGS}}': str(total_tests_with_findings),
            r'{{TESTS_WITHOUT_FINDINGS}}': str(total_tests_without_findings),
        }

        for p in doc.paragraphs:
            for r in p.runs:
                for pattern in handlebar_slugs.keys():
                    if re.search(pattern, r.text):
                        logger.debug('>> Replaced: {old} With: {new}'.format(
                            old=r.text.encode('utf-8'),
                            new=handlebar_slugs[pattern].encode('utf-8')))
                        r.text = re.sub(pattern, handlebar_slugs[pattern],
                                        r.text)

    def get_or_create_mission_data_dir(mission_data_dir):
        if mission_data_dir is None:
            mission_data_dir = os.path.join(
                settings.BASE_DIR, 'SUPPORTING_DATA_PACKAGE',
                str(mission.id) + "_" + str(now().strftime('%Y%m%d-%H%M%S')))
            if not os.path.isdir(mission_data_dir):
                os.makedirs(mission_data_dir)
        return mission_data_dir

    def add_to_data_dir(mission_data_dir, test_case_number, supporting_data):
        # If test case directory path is not created, create it
        path = os.path.join(mission_data_dir, str(test_case_number))

        # Shouldn't have race condition issues, but may need to add
        # try/catch if so later on
        if not os.path.isdir(path):
            os.makedirs(path)

        # Copy file to destination path
        shutil.copy(
            os.path.join(settings.MEDIA_ROOT, supporting_data.filename()),
            path)

    def prepend_classification(text):
        return '(' + system_classification_short + ') ' + text

    def portion_mark_and_insert(paragraphs, document):
        for paragraph in normalize_newlines(paragraphs).split('\n'):
            if len(paragraph) > 0:
                document.add_paragraph(prepend_classification(paragraph))

    # Load the template file to get the styles
    document = Document(settings.REPORT_TEMPLATE_PATH)

    # Get the table templates
    table_no_findings = document.tables[0]
    table_with_findings = document.tables[1]
    data_table = document.tables[2]

    # Set the classification legend color from the background color of the banner
    classification_style = document.styles['Table Classification']
    classification_font = classification_style.font

    # RGBColor doesn't handle shorthand hex codes, so let's just go ahead and expand it
    # if we come across a legacy or "misguided" entry
    if len(system_classification.background_color.hex_color_code) == 3:
        new_hex_code = ''
        for char in system_classification.background_color.hex_color_code:
            new_hex_code += char + char
        system_classification.background_color.hex_color_code = new_hex_code
        system_classification.background_color.save()

    if len(system_classification.text_color.hex_color_code) == 3:
        new_hex_code = ''
        for char in system_classification.text_color.hex_color_code:
            new_hex_code += char + char
        system_classification.text_color.hex_color_code = new_hex_code
        system_classification.text_color.save()

    classification_font.color.rgb = RGBColor.from_string(
        system_classification.get_report_label_color().hex_color_code)

    # Intro H1 and text
    document.add_heading('Introduction', level=1)
    portion_mark_and_insert(mission.introduction, document)

    # Scope H1 and text
    document.add_heading('Scope', level=1)
    portion_mark_and_insert(mission.scope, document)

    # Objectives H1 and text
    document.add_heading('Objectives', level=1)
    portion_mark_and_insert(mission.objectives, document)

    # Exec Summary H1 and text
    document.add_heading('Executive Summary', level=1)
    portion_mark_and_insert(mission.executive_summary, document)

    # Technical Assessment / Attack Architecture and text H1
    document.add_heading('Technical Assessment / Attack Architecture', level=1)
    portion_mark_and_insert(mission.technical_assessment_overview, document)

    # Technical Assessment / Test Cases and Results and loop
    document.add_heading('Technical Assessment / Test Cases and Results',
                         level=1)

    # For each test, Test # - Objective  Attack Phase: H2
    """
    Note: If a test case is hidden from the report, the test_case number and the auto-generated paragraph
    number in Word won't align and it could cause confusion. The team may need to discuss how they want to
    handle this situation.
    """
    """
    WARNING

    Hidden test cases are NOT numbered in the report so the customer doesn't think something was
    accidentally left out. This will result in test case numbering differing between report and web when
    one or more test cases are hidden from the report.
    """

    test_case_number = 0
    tests_with_findings = 0
    tests_without_findings = 0

    # Let's just always craete a mission data dir when zipping attachments on report generation; this way
    # mission attachments will always return a zip file... it just may be empty - located here to account for times
    # when Get Attachments is actuated, but there are no test cases yet.
    if zip_attachments:
        mission_data_dir = get_or_create_mission_data_dir(mission_data_dir)

    for t in tests:

        if test_case_number > 0:
            document.add_page_break()

        test_case_number += 1

        if t.has_findings:
            test_title = "*"
            tests_with_findings += 1
        else:
            test_title = ""
            tests_without_findings += 1

        if t.enclave:
            test_title += "(%s) %s" % (t.enclave, t.test_objective)
        else:
            test_title += "%s" % (t.test_objective, )
        document.add_heading(test_title, level=2)

        # Duplicate one of the pre-made tables; if this is the last of a specific type of
        # test case (findings / no findings), use the cut operation to remove the blank
        # table.
        #TODO: convert to logging: print("T w/ F: {0}\nTotal: {1}\nT w/o F: {2}\nTotal: {3}".format(tests_with_findings, total_tests_with_findings, tests_without_findings, total_tests_without_findings))
        is_last_test_case = True if test_case_number == total_reportable_tests else False
        if t.has_findings:
            if tests_with_findings == total_tests_with_findings or is_last_test_case:
                table = copy_table(document, table_with_findings, cut=True)
            else:
                table = copy_table(document, table_with_findings, cut=False)
        else:
            if tests_without_findings == total_tests_without_findings or is_last_test_case:
                table = copy_table(document, table_no_findings, cut=True)
            else:
                table = copy_table(document, table_no_findings, cut=False)

        # Classification Marking - Top
        cell = table.cell(0, 0)
        get_cleared_paragraph(cell).text = system_classification_verbose

        # Classification Marking - Bottom
        cell = table.cell(16, 1)
        get_cleared_paragraph(cell).text = system_classification_verbose

        # Test Case Number (Table Header Row)
        cell = table.cell(1, 0)
        get_cleared_paragraph(cell).text = 'Test #{0}'.format(test_case_number)

        row_number = 0

        #
        # Test Case Title (Table Header Row)
        #
        row_number += 1
        cell = table.cell(row_number, 1)
        get_cleared_paragraph(cell).text = t.test_objective

        #
        # Attack Phase / Type
        #
        row_number += 1

        include_attack_phase = False
        include_attack_type = False

        if mission.attack_phase_include_flag \
                and t.attack_phase_include_flag \
                and len(t.get_attack_phase_display())> 0:
            include_attack_phase = True

        if mission.attack_type_include_flag \
                and t.attack_type_include_flag \
                and len(t.attack_type) > 0:
            include_attack_type = True

        left_cell = table.cell(row_number, 0)
        right_cell = table.cell(row_number, 1)

        if include_attack_phase or include_attack_type:
            if include_attack_phase and include_attack_type:
                # Table text in column 1 assumes both items are included already
                right_cell.text = ' - '.join(
                    [t.get_attack_phase_display(), t.attack_type])
            elif include_attack_phase:
                get_cleared_paragraph(left_cell).text = "Attack Phase:"
                right_cell.text = t.get_attack_phase_display()
            elif include_attack_type:
                get_cleared_paragraph(left_cell).text = "Attack Type:"
                right_cell.text = t.attack_type
        else:
            logger.debug('Removing Attack Phase/Type Row')
            remove_row(table, table.rows[row_number])
            row_number -= 1

        #
        # Assumptions
        #
        row_number += 1
        if mission.assumptions_include_flag and t.assumptions_include_flag:
            cell = table.cell(row_number, 1)
            cell.text = standardize_report_output_field(t.assumptions)
        else:
            logger.debug('Removing Assumptions Row')
            remove_row(table, table.rows[row_number])
            row_number -= 1

        #
        # Description
        #
        row_number += 1
        if mission.test_description_include_flag and t.test_description_include_flag:
            cell = table.cell(row_number, 1)
            cell.text = standardize_report_output_field(t.test_description)
        else:
            logger.debug('Removing Description Row')
            remove_row(table, table.rows[row_number])
            row_number -= 1

        #
        # Findings
        #
        row_number += 1
        if mission.findings_include_flag and t.findings_include_flag:
            cell = table.cell(row_number, 1)
            cell.text = standardize_report_output_field(t.findings)
        else:
            logger.debug('Removing Findings Row')
            remove_row(table, table.rows[row_number])
            row_number -= 1

        #
        # Mitigations
        #
        row_number += 1
        if mission.mitigation_include_flag and t.mitigation_include_flag:
            cell = table.cell(row_number, 1)
            cell.text = standardize_report_output_field(t.mitigation)
        else:
            logger.debug('Removing Mitigations Row')
            remove_row(table, table.rows[row_number])
            row_number -= 1

        #
        # Tools
        #
        row_number += 1
        if mission.tools_used_include_flag and t.tools_used_include_flag:
            cell = table.cell(row_number, 1)
            cell.text = standardize_report_output_field(t.tools_used)
        else:
            logger.debug('Removing Tools Row')
            remove_row(table, table.rows[row_number])
            row_number -= 1

        #
        # Commands / Syntax
        #
        row_number += 1
        if mission.command_syntax_include_flag and t.command_syntax_include_flag:
            cell = get_cleared_paragraph(table.cell(row_number, 1))
            cell.style = 'Normal-LeftAlign'
            cell.text = standardize_report_output_field(t.command_syntax)
        else:
            logger.debug('Removing Commands/Syntax Row')
            remove_row(table, table.rows[row_number])
            row_number -= 1

        #
        # Targets
        #
        row_number += 1
        if mission.targets_include_flag and t.targets_include_flag:
            cell = table.cell(row_number, 1)
            cell.text = '\n'.join([str(x) for x in t.target_hosts.all()])
        else:
            logger.debug('Removing Targets Row')
            remove_row(table, table.rows[row_number])
            row_number -= 1

        #
        # Sources
        #
        row_number += 1
        if mission.sources_include_flag and t.sources_include_flag:
            cell = table.cell(row_number, 1)
            cell.text = '\n'.join([str(x) for x in t.source_hosts.all()])

        else:
            logger.debug('Removing Sources Row')
            remove_row(table, table.rows[row_number])
            row_number -= 1

        #
        # Date / Time
        #
        row_number += 1
        if mission.attack_time_date_include_flag and t.attack_time_date_include_flag:
            cell = table.cell(row_number, 1)
            cell.text = localtime(
                t.attack_time_date).strftime('%b %d, %Y @ %I:%M %p')
        else:
            logger.debug('Removing Date/Time Row')
            remove_row(table, table.rows[row_number])
            row_number -= 1

        #
        # Side Effects
        #
        row_number += 1
        if mission.attack_side_effects_include_flag and t.attack_side_effects_include_flag:
            cell = table.cell(row_number, 1)
            cell.text = standardize_report_output_field(t.attack_side_effects)
        else:
            logger.debug('Removing Side Effects Row')
            remove_row(table, table.rows[row_number])
            row_number -= 1

        #
        # Details
        #
        row_number += 1
        if mission.test_result_observation_include_flag and t.test_result_observation_include_flag:
            cell = table.cell(row_number, 1)
            cell.text = standardize_report_output_field(
                t.test_result_observation)
        else:
            logger.debug('Removing Details Row')
            remove_row(table, table.rows[row_number])
            row_number -= 1

        #
        # Supporting Data
        #
        row_number += 1
        supporting_data_cell = None
        supporting_data_row = None
        if mission.supporting_data_include_flag:
            supporting_data_cell = table.cell(row_number, 1)
            supporting_data_row = table.rows[row_number]
        else:
            logger.debug('Removing Supporting Data Row')
            remove_row(table, table.rows[row_number])
            row_number -= 1

        #
        # Notes - Used for post report generation notes / customer use
        #
        row_number += 1
        if False:  #TODO: add mission-level toggle
            logger.debug('Removing Customer Notes Row')
            remove_row(table, table.rows[row_number])
            row_number -= 1

        # Attachments section

        supporting_data_cell_items = []

        if mission.supporting_data_include_flag:
            my_data = SupportingData.objects.filter(
                test_detail_id=t.id).filter(include_flag=True)

            if len(my_data) > 0:

                is_first_screenshot = True

                for d in my_data:
                    allowed_image_types = [
                        'gif',
                        'tiff',
                        'jpeg',
                        'bmp',
                        'png',
                    ]
                    try:
                        file_path = os.path.join(settings.MEDIA_ROOT,
                                                 d.filename())
                        logger.debug(
                            '>> Beginning processing of {} at {}.'.format(
                                d.filename(),
                                file_path,
                            ))

                        if imghdr.what(file_path) not in allowed_image_types:
                            raise UnrecognizedImageError(
                                'File type is not in the allowed image types. '
                                'Handling as non-image.')

                        if is_first_screenshot:
                            document.add_heading('Screenshots / Diagrams',
                                                 level=3)
                            logger.debug(
                                'This is the first screenshot of this test case.'
                            )
                            is_first_screenshot = False

                        image_table = copy_table(document, data_table)
                        logger.debug('Creating a new image table.')
                        document.add_paragraph()

                        # Classification Marking - Top
                        cell = image_table.cell(0, 0)
                        get_cleared_paragraph(
                            cell).text = system_classification_verbose

                        # Classification Marking - Bottom
                        cell = image_table.cell(2, 0)
                        get_cleared_paragraph(
                            cell).text = system_classification_verbose

                        content_cell = image_table.cell(1, 0)

                        get_cleared_paragraph(
                            content_cell).add_run().add_picture(
                                d.test_file, width=Inches(5))
                        content_cell.paragraphs[0].add_run("\r" + d.caption)

                    except UnrecognizedImageError as e:
                        logger.debug(
                            '>> Attachment {attachment_name} not recognized as an image; adding as file.'
                            .format(attachment_name=d.filename()))
                        supporting_data_cell_items.append(
                            '- {filename}: {caption}'.format(
                                filename=d.filename(),
                                caption=d.caption,
                            ))

                        if zip_attachments:
                            add_to_data_dir(mission_data_dir, test_case_number,
                                            d)
                    except (InvalidImageStreamError,
                            UnexpectedEndOfFileError) as e:
                        logger.warning(
                            '>> Attempting to add {file_name} to the report output resulted in an error: '
                            '\n{trace}'.format(file_name=d.filename,
                                               trace=traceback.format_exc(10)))
                    except OSError as e:
                        logger.warning(
                            '>> Attempting to add {file_name} to the report output resulted in an error: '
                            '\n{trace}'.format(file_name=d.filename,
                                               trace=traceback.format_exc(10)))
                        try:
                            if not d.test_file.closed:
                                d.test_file.close()
                        except IOError as e:
                            logger.warning(
                                '>> Attempting to close {file_name} resulted in an error: '
                                '\n{trace}'.format(
                                    file_name=d.filename,
                                    trace=traceback.format_exc(10)))
                            pass

                if len(supporting_data_cell_items) > 0:
                    logger.debug(
                        'There are {} data cell items for TC {}.'.format(
                            len(supporting_data_cell_items), t.id))
                    get_cleared_paragraph(
                        supporting_data_cell).text = '\n'.join(
                            supporting_data_cell_items)

        if len(supporting_data_cell_items) == 0:
            logger.debug(
                'There are no supporting_data_cell_items; removing the supporting data row.'
            )
            remove_row(table, supporting_data_row)

    # Conclusion H1 and text
    document.add_heading('Conclusion', level=1)
    portion_mark_and_insert(mission.conclusion, document)

    data_table.cell(0, 0).text = ""
    get_cleared_paragraph(
        data_table.cell(1, 0)
    ).text = "This table is used during report generation and can be deleted in the final report output."
    data_table.cell(2, 0).text = ""

    # Replace document slugs
    replace_document_slugs(document)

    if zip_attachments:
        zip_file = shutil.make_archive(mission_data_dir, 'zip',
                                       mission_data_dir)
        with open(mission_data_dir + '.zip', 'rb') as f:
            return io.BytesIO(f.read())

    else:
        my_stream = StringIO()
        document.save(my_stream)
        return my_stream
Ejemplo n.º 29
0
 def rgb_get_fixture(self, request):
     r_cxml, rgb = request.param
     color_format = ColorFormat(element(r_cxml))
     expected_value = None if rgb is None else RGBColor.from_string(rgb)
     return color_format, expected_value
Ejemplo n.º 30
0
fpname = sys.argv[1]
outfpn = sys.argv[2]

#############################################

# configurable parameters (#TODO: configuration file/CL options)
# refmarker = '\[\d*\].*'  # regexp to recognize a bibliography item: "[decimal number]"
refmarker = '\[\d.*'  # regexp to recognize a bibliography item: "[decimal"
doistr = 'DOI:'  #pre-fix to be recognised for link creation
urlbase = 'https://dx.doi.org/'  #pre-fix for assembling link
linkrgb = '0563C1'  #colour of links
linkunderline = True  #underline links?

# parameter-derived variables
linkRGBcolor = RGBColor.from_string(linkrgb)

#############################################


def add_run_copy(paragraph, run, text=None):
    """Add a 'run' at the end of a paragraph using a 'run' template.
    
    A 'run' is a part of a paragraph with identically formatted text
    each time character formatting changes, a new 'run' is needed.
    
    source:
    https://github.com/python-openxml/python-docx/issues/519#issuecomment-441710870
    
    I have the impression that not everything is neatly copied
    Don't know why