def makepdf(self, pdfdata1, udct, zeros, sig_attributes): parser = PDFParser(BytesIO(pdfdata1)) document = PDFDocument(parser, fallback=False) log.info('get datas from pdf') prev = document.find_xref(parser) info = document.xrefs[0].trailer['Info'].objid root = document.xrefs[0].trailer['Root'].objid size = document.xrefs[0].trailer['Size'] page_objid = document.catalog['Pages'].objid page = None log.info('check sig attributes...') position = MyConfigLoader().get_pdf_config()['position'] if not sig_attributes: visibility = MyConfigLoader().get_pdf_config()['visibility'] else: visibility = sig_attributes['visibility'] log.info(f'the sign is {visibility}') if visibility == 'visible': position = sig_attributes['position'] log.info(f'position: {position}') page_pos = position['page'] if page_pos == 'n': try: pages_count = document.getobj(page_objid)['Count'] page = document.getobj(page_objid)['Kids'][pages_count - 1].objid except Exception: page = int(1) else: try: page = document.getobj(page_objid)['Kids'][int(page_pos) - 1].objid except Exception: log.error('page not found...take the first') page = document.getobj(page_objid)['Kids'][0].objid infodata = self.getdata(pdfdata1, info, prev, document).strip() rootdata = self.getdata(pdfdata1, root, prev, document).strip() pagedata = self.getdata(pdfdata1, page, prev, document).strip() no = size multiple_signs = False signatures = self.get_signature_names(document) if len(signatures) > 0: multiple_signs = True if visibility == 'visible': rect_array = self.get_rect_array(pagedata, position) stream_name = compress(STREAM_WITH_NAME % udct[b'name']) if multiple_signs: objs = self.make_multi_visible_sig_objs(document, udct, no, page, pagedata, infodata, rootdata, stream_name, rect_array, zeros) xref = self.make_multi_visible_xref() new_size = 11 else: objs = self.make_visible_sig_objs(udct, no, page, pagedata, infodata, rootdata, stream_name, rect_array, zeros) xref = self.make_visible_xref() new_size = 13 else: if multiple_signs: objs = self.make_multi_inv_sig_objs(document, udct, no, page, pagedata, infodata, rootdata, zeros, len(signatures) + 1) xref = self.make_multi_inv_xref() new_size = 5 else: objs = self.make_invisible_sig_objs(udct, no, page, pagedata, infodata, rootdata, zeros) xref = self.make_multi_inv_xref() new_size = 5 pdfdata2 = b''.join(objs) startxref = len(pdfdata1) dct = { b'page': page, b'no': no, b'startxref': startxref + len(pdfdata2), b'prev': prev, b'info': no + 0, b'root': no + 1, b'size': no + new_size, b'p0': startxref + pdfdata2.find(b'\n%d 0 obj\n' % page) + 1, b'h1': hashlib.md5(pdfdata1).hexdigest().upper().encode('ascii'), b'h2': hashlib.md5(pdfdata2).hexdigest().upper().encode('ascii'), } for i in range(new_size): dct.update(({b'n%d' % i: startxref + pdfdata2.find(b'\n%d 0 obj\n' % (no + i)) + 1, })) trailer = b'''\ trailer <</ID [<%(h1)s><%(h2)s>]/Info %(info)d 0 R/Prev %(prev)d/Root %(root)d 0 R/Size %(size)d>>\n\ startxref\n\ %(startxref)d\n\ %%%%EOF\n\ ''' xref = xref % dct trailer = trailer % dct pdfdata2 = pdfdata2 + xref + trailer return pdfdata2
def makepdf(self, pdfdata1, udct, zeros): parser = PDFParser(BytesIO(pdfdata1)) document = PDFDocument(parser, fallback=False) prev = document.find_xref(parser) info = document.xrefs[0].trailer['Info'].objid root = document.xrefs[0].trailer['Root'].objid size = 1 # calculate last object id, size is only xref size but not count of object in xref for ref in document.xrefs: if isinstance(ref, PDFXRefStream): no = max(ref.ranges, key=operator.itemgetter(1))[1] else: if len(ref.offsets) == 0: no = 0 else: no = max(ref.offsets.keys()) size = max(size, no) page = document.getobj( document.catalog['Pages'].objid)['Kids'][0].objid nsig, fields = self.getfields(root, document) annots = self.getannots(page, document) infodata = self.getdata(pdfdata1, info, prev, document) rootdata = self.getdata(pdfdata1, root, prev, document, ('AcroForm', )) pagedata = self.getdata(pdfdata1, page, prev, document, ('Annots', )) annotation = udct.get(b'signature', b'').decode('utf8') x1, y1, x2, y2 = udct.get(b'signaturebox', (0, 0, 0, 0)) annotation = FreeText( Location(x1=x1, y1=y1, x2=x2, y2=y2, page=0), Appearance( fill=[0, 0, 0], stroke_width=1, wrap_text=True, font_size=12, content=annotation, ), ) pdfa = annotation.as_pdf_object(identity(), page=None) pdfar = b'[%d %d %d %d]' % tuple(pdfa.Rect) pdfas = pdfa.AP.N.stream.encode('latin1') no = size + 1 objs = [ self.makeobj(page, (b'/Annots[%s%d 0 R]' % (annots, no + 3) + pagedata)), self.makeobj(no + 0, infodata), self.makeobj(no + 1, (b'/AcroForm %d 0 R' % (no + 2)) + rootdata), self.makeobj( no + 2, b'/Fields[%s%d 0 R]/SigFlags %d' % (fields, no + 3, udct[b'sigflags'])), self.makeobj( no + 3, b''' /Type /Annot /Subtype /FreeText /AP <</N %d 0 R>> /BS <</S /S /Type /Border /W 0>> /C [] /Contents (%s) /DA (0 0 0 rg /%s 12 Tf) /Rect %s /F 704 /P %d 0 R /FT /Sig /T(Signature%d) /V %d 0 R ''' % (no + 4, pdfa.Contents.encode('latin1'), pdfa.AP.N.Resources.Font.keys()[0].encode('latin1'), pdfar, page, nsig, no + 5)), self.makeobj( no + 4, b''' /BBox %s /FormType 1 /Length %d /Matrix [1 0 0 1 0 0] /Resources <</Font <<%s <</BaseFont /Helvetica /Encoding /WinAnsiEncoding /Subtype /Type1 /Type /Font>>>> /ProcSet /PDF>> /Subtype /Form /Type /XObject ''' % ( pdfar, len(pdfas), pdfa.AP.N.Resources.Font.keys()[0].encode('latin1'), ), b'stream\n' + pdfas + b'\nendstream\n'), self.makeobj(no + 5, ( b'/ByteRange [0000000000 0000000000 0000000000 0000000000]/ContactInfo(%s)\ /Filter/Adobe.PPKLite/Location(%s)/M(D:%s)/Prop_Build<</App<</Name/>>>>/Reason(%s)/SubFilter/adbe.pkcs7.detached/Type/Sig\ /Contents <' % (udct[b'contact'], udct[b'location'], udct[b'signingdate'], udct[b'reason'])) + zeros + b'>'), ] pdfdata2 = b''.join(objs) xref = b'''\ xref\n\ %(page)d 1\n\ %(p0)010d 00000 n \n\ %(no)d 6\n\ %(n0)010d 00000 n \n\ %(n1)010d 00000 n \n\ %(n2)010d 00000 n \n\ %(n3)010d 00000 n \n\ %(n4)010d 00000 n \n\ %(n5)010d 00000 n \n\ ''' startxref = len(pdfdata1) dct = { b'page': page, b'no': no, b'startxref': startxref + len(pdfdata2), b'prev': prev, b'info': no + 0, b'root': no + 1, b'size': 6, b'p0': startxref + pdfdata2.find(b'\n%d 0 obj\n' % page) + 1, b'n0': startxref + pdfdata2.find(b'\n%d 0 obj\n' % (no + 0)) + 1, b'n1': startxref + pdfdata2.find(b'\n%d 0 obj\n' % (no + 1)) + 1, b'n2': startxref + pdfdata2.find(b'\n%d 0 obj\n' % (no + 2)) + 1, b'n3': startxref + pdfdata2.find(b'\n%d 0 obj\n' % (no + 3)) + 1, b'n4': startxref + pdfdata2.find(b'\n%d 0 obj\n' % (no + 4)) + 1, b'n5': startxref + pdfdata2.find(b'\n%d 0 obj\n' % (no + 5)) + 1, b'h1': hashlib.md5(pdfdata1).hexdigest().upper().encode('ascii'), b'h2': hashlib.md5(pdfdata2).hexdigest().upper().encode('ascii'), } trailer = b'''\ trailer <</ID [<%(h1)s><%(h2)s>]/Info %(info)d 0 R/Prev %(prev)d/Root %(root)d 0 R/Size %(size)d>>\n\ startxref\n\ %(startxref)d\n\ %%%%EOF\n\ ''' xref = xref % dct trailer = trailer % dct pdfdata2 = pdfdata2 + xref + trailer return pdfdata2
def makepdf(self, pdfdata1, udct, zeros): parser = PDFParser(BytesIO(pdfdata1)) document = PDFDocument(parser, fallback=False) prev = document.find_xref(parser) info = document.xrefs[0].trailer['Info'].objid root = document.xrefs[0].trailer['Root'].objid size = 1 # calculate last object id, size is only xref size but not count of object in xref for ref in document.xrefs: if isinstance(ref, PDFXRefStream): no = max(ref.ranges, key=operator.itemgetter(1))[1] else: if len(ref.offsets) == 0: no = 0 else: no = max(ref.offsets.keys()) size = max(size, no) page = document.getobj( document.catalog['Pages'].objid)['Kids'][0].objid nsig, fields = self.getfields(root, document) annots = self.getannots(page, document) infodata = self.getdata(pdfdata1, info, prev, document) rootdata = self.getdata(pdfdata1, root, prev, document, ('AcroForm', )) pagedata = self.getdata(pdfdata1, page, prev, document, ('Annots', )) rectPos = b'0 0 0 0' if b'rectPos' in udct: rectPos = udct[b'rectPos'] no = size + 1 objs = [ self.makeobj(page, (b'/Annots[%s%d 0 R]' % (annots, no + 3) + pagedata)), self.makeobj(no + 0, infodata), self.makeobj(no + 1, (b'/AcroForm %d 0 R' % (no + 2)) + rootdata), self.makeobj( no + 2, b'/Fields[%s%d 0 R]/SigFlags %d' % (fields, no + 3, udct[b'sigflags'])), self.makeobj( no + 3, b'/AP<</N %d 0 R>>/F 132/FT/Sig/P %d 0 R/Rect[%s]/Subtype/Widget/T(Signature%d)/V %d 0 R' % (no + 4, page, rectPos, nsig, no + 5)), self.makeobj( no + 4, b'/BBox[0 0 0 0]/Filter/FlateDecode/Length 8/Subtype/Form/Type/XObject', b'stream\n\x78\x9C\x03\x00\x00\x00\x00\x01\nendstream\n'), self.makeobj(no + 5, ( b'/ByteRange [0000000000 0000000000 0000000000 0000000000]/ContactInfo(%s)\ /Filter/Adobe.PPKLite/Location(%s)/M(D:%s)/Prop_Build<</App<</Name/>>>>/Reason(%s)/SubFilter/adbe.pkcs7.detached/Type/Sig\ /Contents <' % (udct[b'contact'], udct[b'location'], udct[b'signingdate'], udct[b'reason'])) + zeros + b'>'), ] pdfdata2 = b''.join(objs) xref = b'''\ xref\n\ %(page)d 1\n\ %(p0)010d 00000 n \n\ %(no)d 6\n\ %(n0)010d 00000 n \n\ %(n1)010d 00000 n \n\ %(n2)010d 00000 n \n\ %(n3)010d 00000 n \n\ %(n4)010d 00000 n \n\ %(n5)010d 00000 n \n\ ''' startxref = len(pdfdata1) dct = { b'page': page, b'no': no, b'startxref': startxref + len(pdfdata2), b'prev': prev, b'info': no + 0, b'root': no + 1, b'size': 6, b'p0': startxref + pdfdata2.find(b'\n%d 0 obj\n' % page) + 1, b'n0': startxref + pdfdata2.find(b'\n%d 0 obj\n' % (no + 0)) + 1, b'n1': startxref + pdfdata2.find(b'\n%d 0 obj\n' % (no + 1)) + 1, b'n2': startxref + pdfdata2.find(b'\n%d 0 obj\n' % (no + 2)) + 1, b'n3': startxref + pdfdata2.find(b'\n%d 0 obj\n' % (no + 3)) + 1, b'n4': startxref + pdfdata2.find(b'\n%d 0 obj\n' % (no + 4)) + 1, b'n5': startxref + pdfdata2.find(b'\n%d 0 obj\n' % (no + 5)) + 1, b'h1': hashlib.md5(pdfdata1).hexdigest().upper().encode('ascii'), b'h2': hashlib.md5(pdfdata2).hexdigest().upper().encode('ascii'), } trailer = b'''\ trailer <</ID [<%(h1)s><%(h2)s>]/Info %(info)d 0 R/Prev %(prev)d/Root %(root)d 0 R/Size %(size)d>>\n\ startxref\n\ %(startxref)d\n\ %%%%EOF\n\ ''' xref = xref % dct trailer = trailer % dct pdfdata2 = pdfdata2 + xref + trailer return pdfdata2
def makepdf(self, pdfdata1, udct, zeros): parser = PDFParser(BytesIO(pdfdata1)) document = PDFDocument(parser, fallback=False) prev = document.find_xref(parser) info = document.xrefs[0].trailer['Info'].objid root = document.xrefs[0].trailer['Root'].objid size = 1 # calculate last object id, size is only xref size but not count of object in xref for ref in document.xrefs: if isinstance(ref, PDFXRefStream): no = max(ref.ranges, key=operator.itemgetter(1))[1] else: if len(ref.offsets) == 0: no = 0 else: no = max(ref.offsets.keys()) size = max(size, no) pages = len(document.getobj(document.catalog['Pages'].objid)['Kids']) page = udct.get(b'sigpage', 0) if 0 <= udct.get(b'sigpage', 0) <= pages - 1 else 0 page = document.getobj( document.catalog['Pages'].objid)['Kids'][page].objid nsig, fields = self.getfields(root, document) annots = self.getannots(page, document) infodata = self.getdata(pdfdata1, info, prev, document) rootdata = self.getdata(pdfdata1, root, prev, document, ('AcroForm', )) pagedata = self.getdata(pdfdata1, page, prev, document, ('Annots', )) no = size + 1 visualization, nav = self.makevisualization(no, udct, nsig, page) objs = [ self.makeobj(page, (b'/Annots[%s%d 0 R]' % (annots, no + 3) + pagedata)), self.makeobj(no + 0, infodata), self.makeobj(no + 1, (b'/AcroForm %d 0 R' % (no + 2)) + rootdata), self.makeobj( no + 2, b'/Fields[%s%d 0 R]/SigFlags %d' % (fields, no + 3, udct[b'sigflags'])), visualization, self.makeobj(nav + 1, ( b'/ByteRange [0000000000 0000000000 0000000000 0000000000]/ContactInfo(%s)\ /Filter/Adobe.PPKLite/Location(%s)/M(D:%s)/Prop_Build<</App<</Name/>>>>/Reason(%s)/SubFilter/adbe.pkcs7.detached/Type/Sig\ /Contents <' % (udct[b'contact'], udct[b'location'], udct[b'signingdate'], udct[b'reason'])) + zeros + b'>'), # self.makeobj(nav + 1, (b'/ByteRange [0000000000 0000000000 0000000000 0000000000]/ContactInfo(%s)\ #/Filter/Adobe.PPKMS/SubFilter/ETSI.CAdES.detached/Location(%s)/M(D:%s)/Prop_Build<</App<</Name/>>>>/Reason(%s)/SubFilter/adbe.pkcs7.detached/Type/Sig\ #/Contents <' % (udct[b'contact'], udct[b'location'], udct[b'signingdate'], udct[b'reason'])) + zeros + b'>'), ] size = nav - no + 2 pdfdata2 = b''.join(objs) startxref = len(pdfdata1) xref = b'xref\n%d 1\n%010d 00000 n \n%d %d\n' % ( page, startxref + pdfdata2.find(b'\n%d 0 obj\n' % page) + 1, no, size) xref += b''.join([ b'%010d 00000 n \n' % (startxref + pdfdata2.find(b'\n%d 0 obj\n' % (no + i)) + 1) for i in range(size) ]) trailer = b'''\ trailer <</ID [<%(h1)s><%(h2)s>]/Info %(info)d 0 R/Prev %(prev)d/Root %(root)d 0 R/Size %(size)d>>\n\ startxref\n\ %(startxref)d\n\ %%%%EOF\n\ ''' trailer = trailer % { b'page': page, b'no': no, b'startxref': startxref + len(pdfdata2), b'prev': prev, b'info': no + 0, b'root': no + 1, b'size': size, b'h1': hashlib.md5(pdfdata1).hexdigest().upper().encode('ascii'), b'h2': hashlib.md5(pdfdata2).hexdigest().upper().encode('ascii'), } pdfdata2 = pdfdata2 + xref + trailer return pdfdata2
def makepdf(self, pdfdata1, udct, zeros): parser = PDFParser(BytesIO(pdfdata1)) document = PDFDocument(parser, fallback=False) prev = document.find_xref(parser) info = document.xrefs[0].trailer['Info'].objid root = document.xrefs[0].trailer['Root'].objid size = document.xrefs[0].trailer['Size'] page = document.getobj( document.catalog['Pages'].objid)['Kids'][0].objid infodata = self.getdata(pdfdata1, info, prev, document).strip() rootdata = self.getdata(pdfdata1, root, prev, document).strip() pagedata = self.getdata(pdfdata1, page, prev, document).strip() no = size objs = [ self.makeobj(page, (b'/Annots[%d 0 R]' % (no + 3)) + pagedata), self.makeobj(no + 0, infodata), self.makeobj(no + 1, (b'/AcroForm %d 0 R' % (no + 2)) + rootdata), self.makeobj( no + 2, b'/Fields[%d 0 R]/SigFlags %d' % (no + 3, udct[b'sigflags'])), self.makeobj( no + 3, b'/AP<</N %d 0 R>>/F 132/FT/Sig/P %d 0 R/Rect[0 0 0 0]/Subtype/Widget/T(Signature1)/V %d 0 R' % (no + 4, page, no + 5)), self.makeobj( no + 4, b'/BBox[0 0 0 0]/Filter/FlateDecode/Length 8/Subtype/Form/Type/XObject', b'stream\n\x78\x9C\x03\x00\x00\x00\x00\x01\nendstream\n'), self.makeobj(no + 5, ( b'/ByteRange [0000000000 0000000000 0000000000 0000000000]/ContactInfo(%s)\ /Filter/Adobe.PPKLite/Location(%s)/M(D:%s)/Prop_Build<</App<</Name/>>>>/Reason(%s)/SubFilter/adbe.pkcs7.detached/Type/Sig\ /Contents <' % (udct[b'contact'], udct[b'location'], udct[b'signingdate'], udct[b'reason'])) + zeros + b'>'), ] pdfdata2 = b''.join(objs) xref = b'''\ xref\n\ %(page)d 1\n\ %(p0)010d 00000 n \n\ %(no)d 6\n\ %(n0)010d 00000 n \n\ %(n1)010d 00000 n \n\ %(n2)010d 00000 n \n\ %(n3)010d 00000 n \n\ %(n4)010d 00000 n \n\ %(n5)010d 00000 n \n\ ''' startxref = len(pdfdata1) dct = { b'page': page, b'no': no, b'startxref': startxref + len(pdfdata2), b'prev': prev, b'info': no + 0, b'root': no + 1, b'size': 6, b'p0': startxref + pdfdata2.find(b'\n%d 0 obj\n' % page) + 1, b'n0': startxref + pdfdata2.find(b'\n%d 0 obj\n' % (no + 0)) + 1, b'n1': startxref + pdfdata2.find(b'\n%d 0 obj\n' % (no + 1)) + 1, b'n2': startxref + pdfdata2.find(b'\n%d 0 obj\n' % (no + 2)) + 1, b'n3': startxref + pdfdata2.find(b'\n%d 0 obj\n' % (no + 3)) + 1, b'n4': startxref + pdfdata2.find(b'\n%d 0 obj\n' % (no + 4)) + 1, b'n5': startxref + pdfdata2.find(b'\n%d 0 obj\n' % (no + 5)) + 1, b'h1': hashlib.md5(pdfdata1).hexdigest().upper().encode('ascii'), b'h2': hashlib.md5(pdfdata2).hexdigest().upper().encode('ascii'), } trailer = b'''\ trailer <</ID [<%(h1)s><%(h2)s>]/Info %(info)d 0 R/Prev %(prev)d/Root %(root)d 0 R/Size %(size)d>>\n\ startxref\n\ %(startxref)d\n\ %%%%EOF\n\ ''' xref = xref % dct trailer = trailer % dct pdfdata2 = pdfdata2 + xref + trailer return pdfdata2