示例#1
0
    def insert_horizontal_border(paragraph: Paragraph):
        """
        Add an horizontal border under a paragraph.

        Args:
            paragraph: Paragraph under which you want to add an horizontal border.
        """

        # access to XML paragraph element <w:p> and its properties
        p = paragraph._p
        pPr = p.get_or_add_pPr()

        # create new XML element and insert it to the paragraph element
        pBdr = OxmlElement('w:pBdr')
        pPr.insert_element_before(
            pBdr, 'w:shd', 'w:tabs', 'w:suppressAutoHyphens', 'w:kinsoku',
            'w:wordWrap', 'w:overflowPunct', 'w:topLinePunct', 'w:autoSpaceDE',
            'w:autoSpaceDN', 'w:bidi', 'w:adjustRightInd', 'w:snapToGrid',
            'w:spacing', 'w:ind', 'w:contextualSpacing', 'w:mirrorIndents',
            'w:suppressOverlap', 'w:jc', 'w:textDirection', 'w:textAlignment',
            'w:textboxTightWrap', 'w:outlineLvl', 'w:divId', 'w:cnfStyle',
            'w:rPr', 'w:sectPr', 'w:pPrChange')

        # create new XML element, set its properties and add it to the pBdr element
        bottom = OxmlElement('w:bottom')
        bottom.set(qn('w:val'), 'single')
        bottom.set(qn('w:sz'), '6')
        bottom.set(qn('w:space'), '1')
        bottom.set(qn('w:color'), 'auto')
        pBdr.append(bottom)
    def insert_toc(self):
        paragraph = self.document.add_paragraph()
        run = paragraph.add_run()
        fldChar = OxmlElement('w:fldChar')  # creates a new element
        fldChar.set(qn('w:fldCharType'), 'begin')  # sets attribute on element
        instrText = OxmlElement('w:instrText')
        instrText.set(qn('xml:space'), 'preserve')  # sets attribute on element
        instrText.text = 'TOC \\o "1-3" \\h \\z \\u'  # change 1-3 depending on heading levels you need

        fldChar2 = OxmlElement('w:fldChar')
        fldChar2.set(qn('w:fldCharType'), 'separate')
        # fldChar3 = OxmlElement('w:t')
        fldChar3 = OxmlElement('w:updateFields')
        fldChar3.set(qn('w:val'), 'true')
        # fldChar3.text = "Right-click to update field."
        fldChar2.append(fldChar3)

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

        r_element = run._r
        r_element.append(fldChar)
        r_element.append(instrText)
        r_element.append(fldChar2)
        r_element.append(fldChar4)
        p_element = paragraph._p
示例#3
0
def add_table_of_contents(document, label='Table of Contents'):
    document.add_heading(label, level=1)
    paragraph = document.add_paragraph()
    run = paragraph.add_run()
    fldChar = OxmlElement('w:fldChar')  # creates a new element
    fldChar.set(qn('w:fldCharType'), 'begin')  # sets attribute on element
    instrText = OxmlElement('w:instrText')
    instrText.set(qn('xml:space'), 'preserve')  # sets attribute on element
    instrText.text = r'TOC \o "1-3" \h \z \u'  # change 1-3 depending on heading levels you need

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

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

    r_element = run._r
    r_element.append(fldChar)
    r_element.append(instrText)
    r_element.append(fldChar2)
    r_element.append(fldChar4)
    p_element = paragraph._p
    return document
示例#4
0
 def new(cls, pic_id, image_filename):
     nvPicPr = OxmlElement('pic:nvPicPr')
     nvPicPr.append(CT_NonVisualDrawingProps.new(
         'pic:cNvPr', pic_id, image_filename
     ))
     nvPicPr.append(CT_NonVisualPictureProperties.new())
     return nvPicPr
示例#5
0
    def set_table_margins(self, tbl, width: dict = None):
        """
        <w:tbl>
            <w:tblPr>
                    <w:tblStyle w:val="LightShading"/>
                    <w:tblW w:type="auto" w:w="0"/>
                    <w:tblCellMar>
                            <w:left w:type="dxa" w:w="63"/>
                            <w:right w:type="dxa" w:w="63"/>
                    </w:tblCellMar>
                    <w:tblLook w:firstColumn="1" w:firstRow="1" w:lastColumn="0" w:lastRow="0" w:noHBand="0" w:noVBand="1" w:val="04A0"/>
            </w:tblPr>
        """  # noqa

        # 67 = Cm(0.11) ...?
        if width is None:
            width = dict(left=67, right=67)

        margins = OxmlElement('w:tblCellMar')

        for side, w in width.items():
            margin = OxmlElement(f'w:{side}')
            margin.set(qn('w:w'), str(w))
            margin.set(qn('w:type'), 'dxa')

            margins.append(margin)

        tbl._tbl.tblPr.append(margins)
示例#6
0
def generate_pw_toc(document):
    global gl_font_size
    add_simple_par(document, "", gl_font_size, align=docx.enum.text.WD_ALIGN_PARAGRAPH.CENTER, bold=False, breakpar=True)
    document.add_heading("Spis treści", 1)

    paragraph = document.add_paragraph()
    run = paragraph.add_run()
    fldChar = OxmlElement('w:fldChar')  # creates a new element
    fldChar.set(qn('w:fldCharType'), 'begin')  # sets attribute on element
    instrText = OxmlElement('w:instrText')
    instrText.set(qn('xml:space'), 'preserve')  # sets attribute on element
    instrText.text = 'TOC \\o "1-2" \\h \\z \\u'  # change 1-3 depending on heading levels you need

    fldChar2 = OxmlElement('w:fldChar')
    fldChar2.set(qn('w:fldCharType'), 'separate')
    fldChar3 = OxmlElement('w:t')
    fldChar3.text = "Kliknij prawym klawiszem myszki, aby zaktualizować spis treści."
    fldChar2.append(fldChar3)

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

    r_element = run._r
    r_element.append(fldChar)
    r_element.append(instrText)
    r_element.append(fldChar2)
    r_element.append(fldChar4)
    p_element = paragraph._p
示例#7
0
def add_url_hyperlink(paragraph, url: str, text: str):
    """Add URL hyperlink in docx report. Adapted from https://stackoverflow.com/a/47666747/906385

    Args:
        paragraph: a docx paragraph object
        url (str): The URL
        text (str): The text to display
    """
    # This gets access to the document.xml.rels file and gets a new relation id value
    part = paragraph.part
    r_id = part.relate_to(url,
                          constants.RELATIONSHIP_TYPE.HYPERLINK,
                          is_external=True)

    # Create the w:hyperlink tag and add needed values
    hyperlink = OxmlElement("w:hyperlink")
    hyperlink.set(qn("r:id"), r_id)

    # Create a w:r element and a new w:rPr element
    new_run = OxmlElement("w:r")
    rPr = OxmlElement("w:rPr")

    # Join all the xml elements together add add the required text to the w:r element
    new_run.append(rPr)
    new_run.text = text
    hyperlink.append(new_run)

    # Create a new Run object and add the hyperlink into it
    run = paragraph.add_run()
    run._r.append(hyperlink)

    # A workaround for the lack of a hyperlink style (doesn't go purple after using the link)
    # Delete this if using a template that has the hyperlink style in it
    run.font.color.theme_color = dml.MSO_THEME_COLOR_INDEX.HYPERLINK
    run.font.underline = True
示例#8
0
 def add_drawing(self, inline_or_anchor):
     """
     Return a newly appended ``CT_Drawing`` (``<w:drawing>``) child
     element having *inline_or_anchor* as its child.
     """
     drawing = OxmlElement('w:drawing')
     self.append(drawing)
     drawing.append(inline_or_anchor)
     return drawing
示例#9
0
 def new(cls):
     """
     Return a new ``<w:tc>`` element, containing an empty paragraph as the
     required EG_BlockLevelElt.
     """
     tc = OxmlElement("w:tc")
     p = CT_P.new()
     tc.append(p)
     return tc
示例#10
0
    def add_tbl_border(self, tbl):
        """Add table bottom border with OxmlElement"""
        borders = OxmlElement('w:tblBorders')
        bottom_border = OxmlElement('w:bottom')
        bottom_border.set(qn('w:val'), 'single')
        bottom_border.set(qn('w:sz'), '4')
        borders.append(bottom_border)

        tbl._tbl.tblPr.append(borders)
示例#11
0
文件: text.py 项目: AEliu/python-docx
 def add_drawing(self, inline_or_anchor):
     """
     Return a newly appended ``CT_Drawing`` (``<w:drawing>``) child
     element having *inline_or_anchor* as its child.
     """
     drawing = OxmlElement('w:drawing')
     self.append(drawing)
     drawing.append(inline_or_anchor)
     return drawing
示例#12
0
 def new(cls):
     """
     Return a new ``<w:tc>`` element, containing an empty paragraph as the
     required EG_BlockLevelElt.
     """
     tc = OxmlElement('w:tc')
     p = CT_P.new()
     tc.append(p)
     return tc
示例#13
0
 def new(cls, num_id, abstractNum_id):
     """
     Return a new ``<w:num>`` element having numId of *num_id* and having
     a ``<w:abstractNumId>`` child with val attribute set to
     *abstractNum_id*.
     """
     abstractNumId = CT_DecimalNumber.new('w:abstractNumId', abstractNum_id)
     num = OxmlElement('w:num', {qn('w:numId'): str(num_id)})
     num.append(abstractNumId)
     return num
示例#14
0
 def new(cls):
     """
     Return a new ``<w:tbl>`` element, containing the required
     ``<w:tblPr>`` and ``<w:tblGrid>`` child elements.
     """
     tbl = OxmlElement('w:tbl')
     tblPr = CT_TblPr.new()
     tbl.append(tblPr)
     tblGrid = CT_TblGrid.new()
     tbl.append(tblGrid)
     return tbl
示例#15
0
 def new(cls, pic_id, filename, rId, cx, cy):
     """
     Return a new ``<pic:pic>`` element populated with the minimal
     contents required to define a viable picture element, based on the
     values passed as parameters.
     """
     pic = OxmlElement('pic:pic', nsmap=nspfxmap('pic', 'r'))
     pic.append(CT_PictureNonVisual.new(pic_id, filename))
     pic.append(CT_BlipFillProperties.new(rId))
     pic.append(CT_ShapeProperties.new(cx, cy))
     return pic
示例#16
0
 def new(cls):
     """
     Return a new ``<w:tbl>`` element, containing the required
     ``<w:tblPr>`` and ``<w:tblGrid>`` child elements.
     """
     tbl = OxmlElement("w:tbl")
     tblPr = CT_TblPr.new()
     tbl.append(tblPr)
     tblGrid = CT_TblGrid.new()
     tbl.append(tblGrid)
     return tbl
示例#17
0
 def new(cls, pic_id, filename, rId, cx, cy):
     """
     Return a new ``<pic:pic>`` element populated with the minimal
     contents required to define a viable picture element, based on the
     values passed as parameters.
     """
     pic = OxmlElement('pic:pic', nsmap=nspfxmap('pic', 'r'))
     pic.append(CT_PictureNonVisual.new(pic_id, filename))
     pic.append(CT_BlipFillProperties.new(rId))
     pic.append(CT_ShapeProperties.new(cx, cy))
     return pic
示例#18
0
 def new(cls, num_id, abstractNum_id):
     """
     Return a new ``<w:num>`` element having numId of *num_id* and having
     a ``<w:abstractNumId>`` child with val attribute set to
     *abstractNum_id*.
     """
     abstractNumId = CT_DecimalNumber.new(
         'w:abstractNumId', abstractNum_id
     )
     num = OxmlElement('w:num', {qn('w:numId'): str(num_id)})
     num.append(abstractNumId)
     return num
示例#19
0
def add_hyperlink(paragraph, url, text, color='0000FF', underline=True):
    """ places a hyperlink within a paragraph object
    """
    part = paragraph.part
    r_id = part.relate_to(url, RELATIONSHIP_TYPE.HYPERLINK, is_external=True)

    hyperlink = OxmlElement('w:hyperlink')
    hyperlink.set(
        qn('r:id'),
        r_id,
    )

    new_run = OxmlElement('w:r')
    rPr = OxmlElement('w:rPr')

    if color is not None:
        c = OxmlElement('w:color')
        c.set(qn('w:val'), color)
        rPr.append(c)

    if not underline:
        u = OxmlElement('w:u')
        u.set(qn('w:val'), 'none')
        rPr.append(u)

    # Join all the xml elements together add add the required text to the w:r element
    new_run.append(rPr)
    new_run.text = text
    hyperlink.append(new_run)

    paragraph._p.append(hyperlink)

    return hyperlink
示例#20
0
    def remove_border(self, row, border=0):
        for cell in row:
            tcPr = cell.tcPr
            tcBorders = OxmlElement('w:tcBorders')
            top = OxmlElement('w:top')
            top.set(qn('w:val'), 'nil')

            left = OxmlElement('w:left')
            left.set(qn('w:val'), 'nil')

            bottom = OxmlElement('w:bottom')
            bottom.set(qn('w:val'), 'nil')
            bottom.set(qn('w:sz'), '4')
            bottom.set(qn('w:space'), '0')
            bottom.set(qn('w:color'), 'auto')

            right = OxmlElement('w:right')
            right.set(qn('w:val'), 'nil')

            if border == 1:
                tcBorders.append(top)
            if border == 2:
                tcBorders.append(bottom)
            if border == 0:
                tcBorders.append(top)
                tcBorders.append(bottom)
            tcPr.append(tcBorders)
示例#21
0
def add_hyperlink(paragraph, text, url):
	part = paragraph.part
	r_id = part.relate_to(url, RELATIONSHIP_TYPE.HYPERLINK, is_external=True)
	hyperlink = OxmlElement("w:hyperlink")
	hyperlink.set(qn("r:id"), r_id, )
	new_run = OxmlElement("w:r")
	rPr = OxmlElement("w:rPr")
	new_run.append(rPr)
	new_run.text = text
	hyperlink.append(new_run)
	r = paragraph.add_run()
	r._r.append(hyperlink)
	r.font.color.theme_color = MSO_THEME_COLOR_INDEX.HYPERLINK
	r.font.underline = True
	return hyperlink
示例#22
0
    def set_cell_border(cell: _Cell, **kwargs):
        """
        Set the border of a cell.

        Usage example:
        set_cell_border(cell,
                        top={"sz": 12, "val": "single", "color": "#FF0000", "space": "0"},     # top border
                        bottom={"sz": 12, "color": "#00FF00", "val": "single"},     # bottom border
                        start={"sz": 24, "val": "dashed", "shadow": "true"},     # left border
                        end={"sz": 12, "val": "dashed"}     # right border
                        )

        Available attributes can be found here: http://officeopenxml.com/WPtableBorders.php

        Args:
            cell: Cell with borders to be changed.
        """

        # access to XML element <w:tc> and its properties
        tc = cell._tc
        tcPr = tc.get_or_add_tcPr()

        # check for tag existence, if none found, then create one
        tcBorders = tcPr.first_child_found_in("w:tcBorders")
        if tcBorders is None:
            tcBorders = OxmlElement('w:tcBorders')
            tcPr.append(tcBorders)

        # list over all available tags
        for edge in ('start', 'top', 'end', 'bottom', 'insideH', 'insideV'):
            edge_data = kwargs.get(edge)
            if edge_data:
                tag = 'w:{}'.format(edge)

                # check for tag existence, if none found, then create one
                element = tcBorders.find(qn(tag))
                if element is None:
                    element = OxmlElement(tag)
                    tcBorders.append(element)

                # looks like order of attributes is important
                for key in ["sz", "val", "color", "space", "shadow"]:
                    if key in edge_data:
                        element.set(qn('w:{}'.format(key)),
                                    str(edge_data[key]))
示例#23
0
def modifytableborders(table, width, color):
    tbl = table._tbl  # récupération de l'élément XML correspondant à la table
    for cell in tbl.iter_tcs():  # Pour cahque cellule de la table
        tcpr = cell.tcPr  # récupération de l'élément XML tcpr de la cellule
        tcborders = OxmlElement(
            'w:tcborders')  # Création d'un element XML Borders
        # Pour chaque bordure haut, gauche, bas, droite => Ordre important
        for tag in ('w:top', 'w:left', 'w:bottom', 'w:right'):
            element = OxmlElement(
                tag
            )  # création d'un element XML correspondant à la bordure en cours
            element.set(qn('w:sz'), str(width))  # taille de la bordure
            element.set(qn('w:val'), 'single')  # bordure simple
            element.set(qn('w:color'), color)  # couleur de la bordure
            element.set(qn('w:space'), '0')  # espacement entre les bordures
            tcborders.append(
                element)  # ajout de l'élément à l'élément XML borders
        tcpr.append(tcborders)  # Ajout de l'élément XML BORDERS à la cellule
示例#24
0
 def __add_image_from_url(self, cell, image_url):
     margins = ['top', 'start', 'bottom', 'end']
     margin_size = '0'
     tc = cell._tc
     tcPr = tc.get_or_add_tcPr()
     tcMar = OxmlElement('w:tcMar')
     for margin in margins:
         node = OxmlElement('w:%s' % margin)
         node.set(qn('w:w'), margin_size)
         node.set(qn('w:type'), 'dxa')
         tcMar.append(node)
     tcPr.append(tcMar)
     img_width = Mm(40)
     image = self.__get_image_from_url(image_url)
     paragraph = cell.paragraphs[0]
     run = paragraph.add_run()
     run.add_picture(image, width=img_width)
     return True
示例#25
0
def insertHR(paragraph):
    p = paragraph._p  # p is the <w:p> XML element
    pPr = p.get_or_add_pPr()
    pBdr = OxmlElement('w:pBdr')
    pPr.insert_element_before(
        pBdr, 'w:shd', 'w:tabs', 'w:suppressAutoHyphens', 'w:kinsoku',
        'w:wordWrap', 'w:overflowPunct', 'w:topLinePunct', 'w:autoSpaceDE',
        'w:autoSpaceDN', 'w:bidi', 'w:adjustRightInd', 'w:snapToGrid',
        'w:spacing', 'w:ind', 'w:contextualSpacing', 'w:mirrorIndents',
        'w:suppressOverlap', 'w:jc', 'w:textDirection', 'w:textAlignment',
        'w:textboxTightWrap', 'w:outlineLvl', 'w:divId', 'w:cnfStyle', 'w:rPr',
        'w:sectPr', 'w:pPrChange')
    bottom = OxmlElement('w:bottom')
    bottom.set(qn('w:val'), 'single')
    bottom.set(qn('w:sz'), '6')
    bottom.set(qn('w:space'), '1')
    bottom.set(qn('w:color'), 'auto')
    pBdr.append(bottom)
示例#26
0
def add_hyperlink_into_run(paragraph, run, i, url):
    runs = paragraph.runs
    if i is None:
        for i, runi in enumerate(runs):
            if run.text == runi.text:
                break
    # This gets access to the document.xml.rels file and gets a new relation id value
    part = paragraph.part
    r_id = part.relate_to(url, docx.opc.constants.RELATIONSHIP_TYPE.HYPERLINK,
                          is_external=True)

    # Create the w:hyperlink tag and add needed values
    hyperlink = OxmlElement('w:hyperlink')
    hyperlink.set(docx.oxml.shared.qn('r:id'), r_id, )
    hyperlink.append(run._r)
    # see above comment about insert
    # paragraph._p.insert(i+1, hyperlink)
    paragraph._p.append(hyperlink)
    i += 1
    while i < len(runs):
        paragraph._p.append(runs[i]._r)
        i += 1
示例#27
0
def add_hyperlink(paragraph, url, text):
    """
    A function that places a hyperlink within a paragraph object.

    Parameters
    ----------
    paragraph: The paragraph we are adding the hyperlink to.
    url: A string containing the required url
    text: The text displayed for the url

    Returns
    -------
    hyperlink: hyperlink object

    """

    # This gets access to the document.xml.rels file and gets a new relation id value
    part = paragraph.part
    r_id = part.relate_to(url,
                          docx.opc.constants.RELATIONSHIP_TYPE.HYPERLINK,
                          is_external=True)

    # Create the w:hyperlink tag and add needed values
    hyperlink = OxmlElement("w:hyperlink")
    hyperlink.set(qn("r:id"), r_id)

    # Create a w:r element
    new_run = OxmlElement("w:r")

    # Create a new w:rPr element
    rPr = OxmlElement("w:rPr")

    # Style it
    c = OxmlElement("w:color")
    c.set(qn("w:val"), "4F81BD")
    rPr.append(c)
    u = OxmlElement("w:u")
    u.set(qn("w:val"), "none")
    rPr.append(u)

    # Join all the xml elements together add add the required text to the w:r element
    new_run.append(rPr)
    new_run.text = text
    hyperlink.append(new_run)

    paragraph._p.append(hyperlink)

    return hyperlink
def add_hyperlink(paragraph,
                  url,
                  text,
                  font_name=None,
                  underline_hyperlink=True,
                  indent=0,
                  color=True):
    """
    A function that places a hyperlink within a paragraph object.

    :param paragraph: The paragraph we are adding the hyperlink to.
    :param url: A string containing the required url
    :param text: The text displayed for the url
    :return: A Run object containing the hyperlink
    """

    # This gets access to the document.xml.rels file and gets a new relation id value
    part = paragraph.part
    r_id = part.relate_to(url, RT.HYPERLINK, is_external=True)

    # Create the w:hyperlink tag and add needed values
    hyperlink = OxmlElement('w:hyperlink')
    hyperlink.set(
        qn('r:id'),
        r_id,
    )
    hyperlink.set(qn('w:history'), '1')

    # Create a w:r element
    new_run = OxmlElement('w:r')

    # Create a new w:rPr element
    rPr = OxmlElement('w:rPr')

    # Create a w:rStyle element, note this currently does not add the hyperlink style as its not in
    # the default template, I have left it here in case someone uses one that has the style in it
    rStyle = OxmlElement('w:rStyle')
    rStyle.set(qn('w:val'), 'Hyperlink')

    # Join all the xml elements together add add the required text to the w:r element
    rPr.append(rStyle)
    new_run.append(rPr)
    new_run.text = text
    hyperlink.append(new_run)

    # Create a new Run object and add the hyperlink into it
    r = paragraph.add_run()
    r.font.name = font_name
    r._r.append(hyperlink)

    # A workaround for the lack of a hyperlink style (doesn't go purple after using the link)
    # Delete this if using a template that has the hyperlink style in it
    if color:
        r.font.color.theme_color = MSO_THEME_COLOR_INDEX.HYPERLINK
    r.font.underline = underline_hyperlink

    return r
示例#29
0
def add_hyperlink(paragraph, url, text, color, underline):
    """
    A function that places a hyperlink within a paragraph object.

    :param paragraph: The paragraph we are adding the hyperlink to.
    :param url: A string containing the required url
    :param text: The text displayed for the url
    :return: The hyperlink object
    """

    # This gets access to the document.xml.rels file and gets a new relation id value
    part = paragraph.part
    r_id = part.relate_to(url, RELATIONSHIP_TYPE.HYPERLINK, is_external=True)

    # Create the w:hyperlink tag and add needed values
    hyperlink = OxmlElement('w:hyperlink')
    hyperlink.set(
        sharedqn('r:id'),
        r_id,
    )

    # Create a w:r element
    new_run = OxmlElement('w:r')

    # Create a new w:rPr element
    rPr = OxmlElement('w:rPr')

    # Add color if it is given
    if not color is None:
        c = OxmlElement('w:color')
        c.set(sharedqn('w:val'), color)
        rPr.append(c)

    # Remove underlining if it is requested
    if not underline:
        u = OxmlElement('w:u')
        u.set(sharedqn('w:val'), 'none')
        rPr.append(u)

    # Join all the xml elements together add add the required text to the w:r element
    new_run.append(rPr)
    new_run.text = text
    hyperlink.append(new_run)

    paragraph._p.append(hyperlink)

    return hyperlink
示例#30
0
    def new(cls, cx, cy, shape_id, pic):
        """
        Return a new ``<wp:inline>`` element populated with the values passed
        as parameters.
        """
        name = 'Picture %d' % shape_id
        uri = nsmap['pic']

        inline = OxmlElement('wp:inline', nsmap=nspfxmap('wp', 'r'))
        inline.append(CT_PositiveSize2D.new('wp:extent', cx, cy))
        inline.append(CT_NonVisualDrawingProps.new('wp:docPr', shape_id, name))
        inline.append(CT_GraphicalObject.new(uri, pic))
        return inline
def add_hyperlink(paragraph,
                  url,
                  text,
                  font="Times New Roman",
                  size=14,
                  color='0000FF',
                  underline=True):
    # https://github.com/python-openxml/python-docx/issues/74#issuecomment-261169410
    # https://github.com/python-openxml/python-docx/issues/383#issue-220027501

    part = paragraph.part
    r_id = part.relate_to(url, RELATIONSHIP_TYPE.HYPERLINK, is_external=True)
    hyperlink = OxmlElement('w:hyperlink')
    hyperlink.set(
        qn('r:id'),
        r_id,
    )
    new_run = OxmlElement('w:r')
    rPr = OxmlElement('w:rPr')

    c = OxmlElement('w:color')
    c.set(qn('w:val'), color)
    rPr.append(c)

    c = OxmlElement('w:sz')
    c.set(qn('w:val'), str(size * 2))  # size x2 and convert to str (20 == 10)
    rPr.append(c)

    c = OxmlElement('w:rFonts')
    c.set(qn('w:ascii'), font)
    c.set(qn('w:eastAsia'), font)
    c.set(qn('w:hAnsi'), font)
    c.set(qn('w:cs'), font)
    rPr.append(c)

    if not underline:
        u = OxmlElement('w:u')
        u.set(qn('w:val'), 'none')
        rPr.append(u)

    new_run.append(rPr)
    new_run.text = text
    hyperlink.append(new_run)
    paragraph._p.append(hyperlink)
    return hyperlink
示例#32
0
 def new(cls, uri, pic):
     graphicData = OxmlElement('a:graphicData')
     graphicData.set('uri', uri)
     graphicData.append(pic)
     return graphicData
示例#33
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

    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

    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)))
    else:
        template = 'openvasreporting/src/openvas-template.docx'

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

    # ====================
    # DOCUMENT PROPERTIES
    # ====================
    document = Document(template)

    doc_prop = document.core_properties
    doc_prop.title = "OpenVAS Report"
    doc_prop.category = "Report"

    document.add_paragraph('OpenVAS Report', style='Title')

    # ====================
    # TABLE OF CONTENTS
    # ====================
    document.add_paragraph('Table of Contents', style='Heading 1')

    par = document.add_paragraph()
    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 "OV-H1toc;1;OV-H2toc;2;OV-H3toc;3;OV-Finding;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='OV-H1toc')
    document.add_paragraph('< TYPE YOUR MANAGEMENT SUMMARY HERE >')
    document.add_page_break()

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

    # --------------------
    # SUMMARY TABLE
    # --------------------
    document.add_paragraph('Summary', style='OV-H2toc')

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

    table_summary = document.add_table(rows=1, cols=3)
    hdr_cells = table_summary.rows[0].cells
    hdr_cells[0].paragraphs[0].add_run('Risk level').bold = True
    hdr_cells[1].paragraphs[0].add_run('Vulns number').bold = True
    hdr_cells[2].paragraphs[0].add_run('Affected hosts').bold = True

    # 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])

    # --------------------
    # CHART
    # --------------------
    fd, path = tempfile.mkstemp(suffix='.png')

    par_chart = document.add_paragraph()
    run_chart = par_chart.add_run()

    plt.figure()

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

    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='//')
    plt.title('Vulnerability summary by risk level')
    plt.subplot().set_xticks(pos)
    plt.subplot().set_xticklabels(labels_sum)
    plt.gca().spines['left'].set_visible(False)
    plt.gca().spines['right'].set_visible(False)
    plt.gca().spines['top'].set_visible(False)
    plt.gca().spines['bottom'].set_position('zero')
    plt.tick_params(top=False,
                    bottom=True,
                    left=False,
                    right=False,
                    labelleft=False,
                    labelbottom=True)
    plt.subplots_adjust(left=0.0, right=1.0)

    def __label_bars(barcontainer):
        for bar in barcontainer:
            height = bar.get_height()
            plt.gca().text(bar.get_x() + bar.get_width() / 2,
                           bar.get_height() + 0.3,
                           str(int(height)),
                           ha='center',
                           color='black',
                           fontsize=9)

    __label_bars(bars_vuln)
    __label_bars(bars_aff)

    plt.legend()

    plt.savefig(path)

    # plt.show()  # DEBUG

    run_chart.add_picture(path, width=Cm(8.0))

    plt.figure()

    values = list(vuln_by_family.values())
    pie, tx, autotexts = plt.pie(values,
                                 labels=vuln_by_family.keys(),
                                 autopct='')
    plt.title('Vulnerability by family')
    for i, txt in enumerate(autotexts):
        txt.set_text('{}'.format(values[i]))
    plt.axis('equal')

    plt.savefig(
        path, bbox_inches='tight'
    )  # bbox_inches fixes labels being cut, however only on save not on show

    # plt.show()  # DEBUG

    run_chart.add_picture(path, width=Cm(8.0))
    os.close(fd)
    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='OV-H2toc').paragraph_format.page_break_before = True
            cur_level = level
        else:
            document.add_page_break()

        title = "[{}] {}".format(level.upper(), vuln.name)
        document.add_paragraph(title, style='OV-Finding')

        table_vuln = document.add_table(rows=8, cols=3)
        table_vuln.autofit = False

        # 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)

        for col_cell in col_cells:
            col_cell.width = Cm(0.42)

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

        for hdr_cell in hdr_cells:
            hdr_cell.width = Cm(3.58)

        # 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 txt_cell in txt_cells:
            txt_cell.width = Cm(12.50)

        # VULN HOSTS
        # --------------------
        document.add_paragraph('Vulnerable hosts', style='Heading 4')

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

        col_cells = table_hosts.columns[1].cells
        for col_cell in col_cells:
            col_cell.width = Cm(3.2)

        col_cells = table_hosts.columns[2].cells
        for col_cell in col_cells:
            col_cell.width = Cm(3.2)

        col_cells = table_hosts.columns[2].cells
        for col_cell in col_cells:
            col_cell.width = Cm(1.6)

        col_cells = table_hosts.columns[3].cells
        for col_cell in col_cells:
            col_cell.width = Cm(1.6)

        col_cells = table_hosts.columns[4].cells
        for col_cell in col_cells:
            col_cell.width = Cm(6.4)

        hdr_cells = table_hosts.rows[0].cells
        hdr_cells[0].paragraphs[0].add_run('IP').bold = True
        hdr_cells[1].paragraphs[0].add_run('Host name').bold = True
        hdr_cells[2].paragraphs[0].add_run('Port number').bold = True
        hdr_cells[3].paragraphs[0].add_run('Port protocol').bold = True
        hdr_cells[4].paragraphs[0].add_run('Port result').bold = True

        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"

    document.save(output_file)
示例#34
0
def write_report(args, reportDir, lookup, whoisResult, dnsResult, googleResult,
                 shodanResult, pasteScrapeResult, harvesterResult,
                 scrapeResult, credResult, pyfocaResult):

    today = time.strftime("%m/%d/%Y")
    for l in lookup:
        print '[+] Starting OSINT report for ' + l

        #dump to a word doc
        #refs
        #https://python-docx.readthedocs.io/en/latest/user/text.html
        #https://python-docx.readthedocs.io/en/latest/user/quickstart.html

        #create a document
        document = docx.Document()

        #add logo
        document.add_picture('./resources/logo.png', height=Inches(1.25))

        #add domain cover info

        paragraph = document.add_paragraph()
        runParagraph = paragraph.add_run('%s' % l)
        font = runParagraph.font
        font.name = 'Arial'
        font.size = Pt(28)
        font.color.rgb = RGBColor(0x00, 0x00, 0x00)

        #add cover info
        paragraph = document.add_paragraph()
        runParagraph = paragraph.add_run(
            'Open Source Intelligence Report\n\n\n\n\n\n\n\n\n\n\n')
        font = runParagraph.font
        font.name = 'Arial'
        font.size = Pt(26)
        font.color.rgb = RGBColor(0xe9, 0x58, 0x23)

        paragraph = document.add_paragraph()
        runParagraph = paragraph.add_run('Generated on: %s' % today)
        font = runParagraph.font
        font.name = 'Arial'
        font.size = Pt(16)
        font.color.rgb = RGBColor(0x00, 0x00, 0x00)

        #page break for cover page
        document.add_page_break()

        #add intro text on intropage

        heading = document.add_heading()
        runHeading = heading.add_run('Executive Summary')
        font = runHeading.font
        font.name = 'Arial'
        font.size = Pt(20)
        font.color.rgb = RGBColor(0xe9, 0x58, 0x23)

        paragraph = document.add_paragraph()
        runParagraph = paragraph.add_run(
            '\nThis document contains information about network, technology, and people associated with the assessment targets. The information was obtained by programatically querying various free or low cost Internet data sources.\n'
        )
        font = runParagraph.font
        font.name = 'Arial'
        font.size = Pt(11)
        runParagraph = paragraph.add_run(
            '\nThese data include information about the network, technology, and people associated with the targets.\n'
        )
        font = runParagraph.font
        font.name = 'Arial'
        font.size = Pt(11)
        runParagraph = paragraph.add_run(
            '\nSpecific data sources include: whois, domain name system (DNS) records, Google dork results, and data from recent compromises such as LinkedIn. Other sources include results from Shodan, document metadata from theHarvester and pyFoca, as well as queries to Pastebin, Github, job boards, etc. \n'
        )
        font = runParagraph.font
        font.name = 'Arial'
        font.size = Pt(11)

        #page break for cover page
        document.add_page_break()

        heading = document.add_heading()
        runHeading = heading.add_run('Table of Contents')
        font = runHeading.font
        font.bold = True
        font.name = 'Arial'
        font.size = Pt(20)
        font.color.rgb = RGBColor(0x0, 0x0, 0x0)

        #TOC https://github.com/python-openxml/python-docx/issues/36
        paragraph = document.add_paragraph()
        run = paragraph.add_run()
        font.name = 'Arial'
        font.size = Pt(11)
        fldChar = OxmlElement('w:fldChar')  # creates a new element
        fldChar.set(qn('w:fldCharType'), 'begin')  # sets attribute on element

        instrText = OxmlElement('w:instrText')
        instrText.set(qn('xml:space'), 'preserve')  # sets attribute on element
        instrText.text = 'TOC \o "1-3" \h \z \u'  # change 1-3 depending on heading levels you need

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

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

        r_element = run._r
        r_element.append(fldChar)
        r_element.append(instrText)
        r_element.append(fldChar2)
        r_element.append(fldChar4)
        p_element = paragraph._p

        #page break for toc
        document.add_page_break()

        if credResult:
            print '[+] Adding credential dump results to report'
            #header
            heading = document.add_heading(level=3)
            runHeading = heading.add_run(
                'Credentials found from recent compromises (LinkedIn, Adobe, etc.) related to: %s'
                % l)
            font = runHeading.font
            font.name = 'Arial'
            font.color.rgb = RGBColor(0xe9, 0x58, 0x23)
            paragraph = document.add_paragraph()
            for c in credResult:
                runParagraph = paragraph.add_run(''.join(c))
                font = runParagraph.font
                font.name = 'Arial'
                font.size = Pt(11)
            document.add_page_break()

        #add whois data with header and break after end
        if whoisResult:
            print '[+] Adding whois results to report'
            #header
            heading = document.add_heading(level=3)
            runHeading = heading.add_run('Whois Data for: %s' % l)
            font = runHeading.font
            font.name = 'Arial'
            font.color.rgb = RGBColor(0xe9, 0x58, 0x23)
            #content
            paragraph = document.add_paragraph()
            for w in whoisResult:
                runParagraph = paragraph.add_run('\n'.join(w))
                font = runParagraph.font
                font.name = 'Arial'
                font.size = Pt(10)
            document.add_page_break()

        #add dns data with header and break after end
        if dnsResult:
            print '[+] Adding DNS results to report'
            #header
            heading = document.add_heading(level=3)
            runHeading = heading.add_run('Domain Name System Data for: %s' % l)
            font = runHeading.font
            font.name = 'Arial'
            font.color.rgb = RGBColor(0xe9, 0x58, 0x23)
            #content
            paragraph = document.add_paragraph()
            for d in dnsResult:
                runParagraph = paragraph.add_run('\n'.join(d))
                font = runParagraph.font
                font.name = 'Arial'
                font.size = Pt(10)
            document.add_page_break()

        #google dork output
        if googleResult:
            print '[+] Adding google dork results to report'
            #header
            heading = document.add_heading(level=3)
            runHeading = heading.add_run('Google Dork Results for: %s' % l)
            font = runHeading.font
            font.name = 'Arial'
            font.color.rgb = RGBColor(0xe9, 0x58, 0x23)
            #content
            paragraph = document.add_paragraph()
            for r in googleResult:
                runParagraph = paragraph.add_run(''.join(r + '\n'))
                font = runParagraph.font
                font.name = 'Arial'
                font.size = Pt(10)
            document.add_page_break()

        #harvester output
        if harvesterResult:
            print '[+] Adding theHarvester results to report'
            #header
            heading = document.add_heading(level=3)
            runHeading = heading.add_run('theHarvester Results for: %s' % l)
            font = runHeading.font
            font.name = 'Arial'
            font.color.rgb = RGBColor(0xe9, 0x58, 0x23)
            #content
            paragraph = document.add_paragraph()
            for h in harvesterResult:
                runParagraph = paragraph.add_run(''.join(h))
                #set font stuff
                font = runParagraph.font
                font.name = 'Arial'
                font.size = Pt(10)
            document.add_page_break()

        #pastebin scrape output
        if pasteScrapeResult:
            print '[+] Adding pastebin scrape results to report'
            document.add_heading('Pastebin URLs for %s' % l, level=3)
            document.add_paragraph(pasteScrapeResult)
            document.add_page_break()
            #document.add_paragraph(pasteScrapeContent)
            #document.add_page_break()

        #general scrape output
        if scrapeResult:
            print '[+] Adding website scraping results to report'
            #header
            heading = document.add_heading(level=3)
            runHeading = heading.add_run('Website Scraping Results for %s' % l)
            font = runHeading.font
            font.name = 'Arial'
            font.color.rgb = RGBColor(0xe9, 0x58, 0x23)
            #content
            paragraph = document.add_paragraph()
            for sr in scrapeResult:
                runParagraph = paragraph.add_run(sr)
                font = runParagraph.font
                font.name = 'Arial'
                font.size = Pt(10)

            document.add_page_break()

        #pyfoca results
        if pyfocaResult:
            print '[+] Adding pyfoca results to report'
            heading = document.add_heading(level=3)
            runHeading = heading.add_run('pyFoca Results for: %s' % l)
            font = runHeading.font
            font.name = 'Arial'
            font.color.rgb = RGBColor(0xe9, 0x58, 0x23)

            paragraph = document.add_paragraph()
            for fr in pyfocaResult:
                #lolwut
                runParagraph = paragraph.add_run(''.join(
                    str(fr).strip(("\\ba\x00b\n\rc\fd\xc3"))))
                font = runParagraph.font
                font.name = 'Arial'
                font.size = Pt(10)

            document.add_page_break()

        #shodan output
        if shodanResult:
            heading = document.add_heading(level=3)
            runHeading = heading.add_run('Shodan Results for: %s' % l)
            font = runHeading.font
            font.name = 'Arial'
            font.color.rgb = RGBColor(0xe9, 0x58, 0x23)

            paragraph = document.add_paragraph()
            for shr in shodanResult:
                try:
                    runParagraph = paragraph.add_run(
                        str(shr).strip(("\\ba\x00b\n\rc\fd\xc3")))
                    #set font stuff
                    font = runParagraph.font
                    font.name = 'Arial'
                    font.size = Pt(10)
                except:
                    print 'probably an encoding error...'
                    continue

        print '[+] Writing file: ./reports/%s/OSINT_%s_.docx' % (l, l)
        document.save(reportDir + l + '/' + l + 'OSINT_%s_.docx' % l)
示例#35
0
    def Remove_Border(self, row, border=0, outside=False):
        for cell in row:
            tcPr = cell.tcPr
            tcBorders = OxmlElement('w:tcBorders')
            top = OxmlElement('w:top')
            top.set(qn('w:val'), 'nil')

            bottom = OxmlElement('w:bottom')
            bottom.set(qn('w:val'), 'nil')
            bottom.set(qn('w:sz'), '4')
            bottom.set(qn('w:space'), '0')
            bottom.set(qn('w:color'), 'auto')

            right = OxmlElement('w:right')
            right.set(qn('w:val'), 'nil')

            if border == 1:
                tcBorders.append(top)
            if border == 2:
                tcBorders.append(bottom)
            if border == 0:
                tcBorders.append(top)
                tcBorders.append(bottom)
            if border == 3:
                tcBorders.append(right)
                tcBorders.append(left)
                tcBorders.append(top)
                tcBorders.append(bottom)
            tcPr.append(tcBorders)
        index = 0
        if outside == True:
            for cell in row:
                tcPr = cell.tcPr
                tcBorders = OxmlElement('w:tcBorders')
                left = OxmlElement('w:left')
                left.set(qn('w:val'), 'nil')

                right = OxmlElement('w:right')
                right.set(qn('w:val'), 'nil')
                if index == 0:
                    tcBorders.append(left)
                if row.index(cell) == row.index(row[-1]):
                    tcBorders.append(right)
                tcPr.append(tcBorders)
                index += 1
示例#36
0
    def run(self, \
        args, \
        report_directory, \
        lookup, whois_result, \
        dns_result, \
        google_result, \
        shodan_result, \
        paste_scrape_result, \
        theharvester_result, \
        webscrape_result, \
        cred_result, \
        pyfoca_result):

        for l in lookup:

            print('[+] Starting OSINT report for '.format(l))

            self.document = docx.Document()
            #add logo
            self.document.add_picture('./resources/logo.png',
                                      height=Inches(1.25))

            #add domain cover info
            paragraph = self.document.add_paragraph()
            run_paragraph = paragraph.add_run('%s' % l)
            font = run_paragraph.font
            font.name = 'Arial'
            font.size = Pt(28)
            font.color.rgb = RGBColor(0x00, 0x00, 0x00)

            #add cover info
            paragraph = self.document.add_paragraph()
            run_paragraph = paragraph.add_run(
                'Open Source Intelligence Report\n\n\n\n\n\n\n\n\n\n\n')
            font = run_paragraph.font
            font.name = 'Arial'
            font.size = Pt(26)
            font.color.rgb = RGBColor(0xe9, 0x58, 0x23)

            paragraph = self.document.add_paragraph()
            run_paragraph = paragraph.add_run('Generated on: %s' % self.today)
            font = run_paragraph.font
            font.name = 'Arial'
            font.size = Pt(16)
            font.color.rgb = RGBColor(0x00, 0x00, 0x00)

            #page break for cover page
            self.document.add_page_break()

            #add intro text on intropage
            heading = self.document.add_heading()
            run_heading = heading.add_run('Executive Summary')
            font = run_heading.font
            font.name = 'Arial'
            font.size = Pt(20)
            font.color.rgb = RGBColor(0xe9, 0x58, 0x23)

            paragraph = self.document.add_paragraph()
            run_paragraph = paragraph.add_run(
                '\nThis document contains information about network, technology, and people associated with the assessment targets. The information was obtained by programatically querying various free or low cost Internet data sources.\n'
            )
            font = run_paragraph.font
            font.name = 'Arial'
            font.size = Pt(11)
            run_paragraph = paragraph.add_run(
                '\nThese data include information about the network, technology, and people associated with the targets.\n'
            )
            font = run_paragraph.font
            font.name = 'Arial'
            font.size = Pt(11)
            run_paragraph = paragraph.add_run(
                '\nSpecific data sources include: whois, domain name system (DNS) records, Google dork results, and data from recent compromises such as LinkedIn. Other sources include results from Shodan, document metadata from theHarvester and pyFoca, as well as queries to Pastebin, Github, job boards, etc. \n'
            )
            font = run_paragraph.font
            font.name = 'Arial'
            font.size = Pt(11)

            #page break for cover page
            self.document.add_page_break()

            heading = self.document.add_heading()
            run_heading = heading.add_run('Table of Contents')
            font = run_heading.font
            font.bold = True
            font.name = 'Arial'
            font.size = Pt(20)
            font.color.rgb = RGBColor(0x0, 0x0, 0x0)

            #TOC https://github.com/python-openxml/python-docx/issues/36
            paragraph = self.document.add_paragraph()
            run = paragraph.add_run()
            font.name = 'Arial'
            font.size = Pt(11)
            fldChar = OxmlElement('w:fldChar')  # creates a new element
            fldChar.set(qn('w:fldCharType'),
                        'begin')  # sets attribute on element

            instrText = OxmlElement('w:instrText')
            instrText.set(qn('xml:space'),
                          'preserve')  # sets attribute on element
            instrText.text = 'TOC \o "1-3" \h \z \u'  # change 1-3 depending on heading levels you need

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

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

            r_element = run._r
            r_element.append(fldChar)
            r_element.append(instrText)
            r_element.append(fldChar2)
            r_element.append(fldChar4)
            p_element = paragraph._p

            #page break for toc
            self.document.add_page_break()

            if cred_result is not None:
                print('[+] Adding credential dump results to report')
                #header
                heading = self.document.add_heading(level=3)
                run_heading = heading.add_run(
                    'Credentials found from recent compromises (LinkedIn, Adobe, etc.) related to: %s'
                    % l)
                font = run_heading.font
                font.name = 'Arial'
                font.color.rgb = RGBColor(0xe9, 0x58, 0x23)
                paragraph = self.document.add_paragraph()
                for c in cred_result:
                    run_paragraph = paragraph.add_run(''.join(c))
                    font = run_paragraph.font
                    font.name = 'Arial'
                    font.size = Pt(11)
                self.document.add_page_break()

            #add whois data with header and break after end
            if whois_result is not None:
                print('[+] Adding whois results to report')
                #header
                heading = self.document.add_heading(level=3)
                run_heading = heading.add_run('Whois Data for: %s' % l)
                font = run_heading.font
                font.name = 'Arial'
                font.color.rgb = RGBColor(0xe9, 0x58, 0x23)
                #content
                paragraph = self.document.add_paragraph()
                for line in whois_result:
                    if ':' in line:
                        run_paragraph = paragraph.add_run(''.join(line) + '\n')
                        font = run_paragraph.font
                        font.name = 'Arial'
                        font.size = Pt(10)
                self.document.add_page_break()

            #add dns data with header and break after end
            if dns_result is not None:
                print('[+] Adding DNS results to report')
                #header
                heading = self.document.add_heading(level=3)
                run_heading = heading.add_run(
                    'Domain Name System Data for: %s' % l)
                font = run_heading.font
                font.name = 'Arial'
                font.color.rgb = RGBColor(0xe9, 0x58, 0x23)
                #content
                paragraph = self.document.add_paragraph()
                for d in dns_result:
                    run_paragraph = paragraph.add_run('\n'.join(d))
                    font = run_paragraph.font
                    font.name = 'Arial'
                    font.size = Pt(10)
                self.document.add_page_break()

            #google dork output
            if google_result is not None:
                print('[+] Adding google dork results to report')
                #header
                heading = self.document.add_heading(level=3)
                run_heading = heading.add_run('Google Dork Results for: %s' %
                                              l)
                font = run_heading.font
                font.name = 'Arial'
                font.color.rgb = RGBColor(0xe9, 0x58, 0x23)
                #content
                paragraph = self.document.add_paragraph()
                for r in google_result:
                    run_paragraph = paragraph.add_run(''.join(r + '\n'))
                    font = run_paragraph.font
                    font.name = 'Arial'
                    font.size = Pt(10)
                self.document.add_page_break()

            #harvester output
            if theharvester_result is not None:
                print('[+] Adding theHarvester results to report')
                #header
                heading = self.document.add_heading(level=3)
                run_heading = heading.add_run('theHarvester Results for: %s' %
                                              l)
                font = run_heading.font
                font.name = 'Arial'
                font.color.rgb = RGBColor(0xe9, 0x58, 0x23)
                #content
                paragraph = self.document.add_paragraph()
                for h in theharvester_result:
                    run_paragraph = paragraph.add_run(''.join(h))
                    #set font stuff
                    font = run_paragraph.font
                    font.name = 'Arial'
                    font.size = Pt(10)
                self.document.add_page_break()

            #pastebin scrape output
            if paste_scrape_result is not None:
                print('[+] Adding pastebin scrape results to report')
                heading = self.document.add_heading(level=3)
                run_heading = heading.add_run('Pastebin URLs for %s' % l)
                font = run_heading.font
                font.name = 'Arial'
                font.color.rgb = RGBColor(0xe9, 0x58, 0x23)

                paragraph = self.document.add_paragraph()
                self.document.add_paragraph(paste_scrape_result)
                font = run_paragraph.font
                font.name = 'Arial'
                font.size = Pt(10)
                self.document.add_page_break()

            #general scrape output
            if webscrape_result is not None:
                print('[+] Adding website scraping results to report')
                #header
                heading = self.document.add_heading(level=3)
                run_heading = heading.add_run(
                    'Website Scraping Results for %s' % l)
                font = run_heading.font
                font.name = 'Arial'
                font.color.rgb = RGBColor(0xe9, 0x58, 0x23)
                #content
                paragraph = self.document.add_paragraph()
                for sr in webscrape_result:
                    for line in sr:
                        run_paragraph = paragraph.add_run(line)
                        font = run_paragraph.font
                        font.name = 'Arial'
                        font.size = Pt(10)

                self.document.add_page_break()

            #pyfoca results
            if pyfoca_result is not None:
                print('[+] Adding pyfoca results to report')
                heading = self.document.add_heading(level=3)
                run_heading = heading.add_run('pyFoca Results for: %s' % l)
                font = run_heading.font
                font.name = 'Arial'
                font.color.rgb = RGBColor(0xe9, 0x58, 0x23)

                paragraph = self.document.add_paragraph()
                for fr in pyfoca_result:
                    run_paragraph = paragraph.add_run(''.join(
                        str(fr).strip(("\\ba\x00b\n\rc\fd\xc3"))))
                    font = run_paragraph.font
                    font.name = 'Arial'
                    font.size = Pt(10)

                self.document.add_page_break()

            #shodan output
            if shodan_result is not None:
                heading = self.document.add_heading(level=3)
                run_heading = heading.add_run('Shodan Results for: %s' % l)
                font = run_heading.font
                font.name = 'Arial'
                font.color.rgb = RGBColor(0xe9, 0x58, 0x23)

                paragraph = self.document.add_paragraph()
                for shr in shodan_result:
                    try:
                        run_paragraph = paragraph.add_run(
                            str(shr).strip(("\\ba\x00b\n\rc\fd\xc3")))
                        #set font stuff
                        font = run_paragraph.font
                        font.name = 'Arial'
                        font.size = Pt(10)
                    except:
                        print('probably an encoding error...')
                        continue

            print('[+] Writing file: ./reports/{}/OSINT_{}_.docx'.format(l, l))

            #saves to ./reports/domain.com/OSINT_domain.com_.docx
            self.document.save(report_directory +
                               '{}/OSINT_{}_.docx'.format(l, l))