caerp-sign-pdf 2024.1.3__tar.gz → 2024.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- caerp_sign_pdf-2024.2.0/CURRENT_VERSION +1 -0
- {caerp_sign_pdf-2024.1.3 → caerp_sign_pdf-2024.2.0}/PKG-INFO +4 -1
- caerp_sign_pdf-2024.2.0/requirements.txt +1 -0
- {caerp_sign_pdf-2024.1.3 → caerp_sign_pdf-2024.2.0}/src/caerp_sign_pdf/public.py +59 -31
- {caerp_sign_pdf-2024.1.3 → caerp_sign_pdf-2024.2.0}/src/caerp_sign_pdf.egg-info/PKG-INFO +4 -1
- caerp_sign_pdf-2024.2.0/src/caerp_sign_pdf.egg-info/requires.txt +1 -0
- caerp_sign_pdf-2024.1.3/CURRENT_VERSION +0 -1
- caerp_sign_pdf-2024.1.3/requirements.txt +0 -1
- caerp_sign_pdf-2024.1.3/src/caerp_sign_pdf.egg-info/requires.txt +0 -1
- {caerp_sign_pdf-2024.1.3 → caerp_sign_pdf-2024.2.0}/LICENSE.txt +0 -0
- {caerp_sign_pdf-2024.1.3 → caerp_sign_pdf-2024.2.0}/MANIFEST.in +0 -0
- {caerp_sign_pdf-2024.1.3 → caerp_sign_pdf-2024.2.0}/README.rst +0 -0
- {caerp_sign_pdf-2024.1.3 → caerp_sign_pdf-2024.2.0}/setup.cfg +0 -0
- {caerp_sign_pdf-2024.1.3 → caerp_sign_pdf-2024.2.0}/setup.py +0 -0
- {caerp_sign_pdf-2024.1.3 → caerp_sign_pdf-2024.2.0}/src/caerp_sign_pdf/__init__.py +0 -0
- {caerp_sign_pdf-2024.1.3 → caerp_sign_pdf-2024.2.0}/src/caerp_sign_pdf/models.py +0 -0
- {caerp_sign_pdf-2024.1.3 → caerp_sign_pdf-2024.2.0}/src/caerp_sign_pdf.egg-info/SOURCES.txt +0 -0
- {caerp_sign_pdf-2024.1.3 → caerp_sign_pdf-2024.2.0}/src/caerp_sign_pdf.egg-info/dependency_links.txt +0 -0
- {caerp_sign_pdf-2024.1.3 → caerp_sign_pdf-2024.2.0}/src/caerp_sign_pdf.egg-info/not-zip-safe +0 -0
- {caerp_sign_pdf-2024.1.3 → caerp_sign_pdf-2024.2.0}/src/caerp_sign_pdf.egg-info/top_level.txt +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
2024.2.0
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: caerp_sign_pdf
|
|
3
|
-
Version: 2024.
|
|
3
|
+
Version: 2024.2.0
|
|
4
4
|
Summary: caerp_sign_pdf
|
|
5
5
|
Home-page: https://framagit.org/caerp/caerp_sign_pdf
|
|
6
6
|
Author: Kilya
|
|
7
7
|
Author-email: contact@kilya.net
|
|
8
8
|
License: GPLv3
|
|
9
9
|
Keywords: web wsgi bfg pylons pyramid caerp
|
|
10
|
+
Platform: UNKNOWN
|
|
10
11
|
Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
|
|
11
12
|
Classifier: Programming Language :: Python
|
|
12
13
|
Classifier: Framework :: Pyramid
|
|
@@ -69,3 +70,5 @@ Sous linux la signature d'un document PDF peut être vérifiée facilement en li
|
|
|
69
70
|
|
|
70
71
|
pdfsig <monfichierpdf.pdf>
|
|
71
72
|
|
|
73
|
+
|
|
74
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
pyHanko[pkcs11,image-support,opentype,xmp]==0.25.1
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
2
|
import logging
|
|
3
3
|
import hashlib
|
|
4
|
+
import subprocess
|
|
4
5
|
|
|
5
6
|
from io import BytesIO
|
|
6
7
|
from pyhanko.pdf_utils.incremental_writer import IncrementalPdfFileWriter
|
|
7
8
|
from pyhanko.sign import fields, signers
|
|
8
9
|
from pyhanko.sign.general import SigningError
|
|
9
10
|
from pyhanko.stamp import TextStampStyle
|
|
10
|
-
from PyPDF4.pdf import PdfFileReader, PdfFileWriter
|
|
11
11
|
from pyramid.httpexceptions import HTTPUnsupportedMediaType
|
|
12
12
|
|
|
13
13
|
from caerp.views.files.controller import FileData
|
|
@@ -27,6 +27,10 @@ nouveau fichier PDF avant de le recharger."
|
|
|
27
27
|
|
|
28
28
|
|
|
29
29
|
class SignPDFService(object):
|
|
30
|
+
"""
|
|
31
|
+
The PDF digital signing service
|
|
32
|
+
"""
|
|
33
|
+
|
|
30
34
|
def __init__(self, context, request):
|
|
31
35
|
self.context = context
|
|
32
36
|
self.request = request
|
|
@@ -58,18 +62,44 @@ class SignPDFService(object):
|
|
|
58
62
|
"""
|
|
59
63
|
return hashlib.md5(file_data.getvalue()).hexdigest()
|
|
60
64
|
|
|
61
|
-
def
|
|
65
|
+
def _get_clean_pdf(self, file_data: BytesIO) -> BytesIO:
|
|
62
66
|
"""
|
|
63
|
-
Create a new clean PDF buffer from the original
|
|
64
|
-
to avoid some format errors
|
|
67
|
+
Create a new clean PDF buffer from the original to avoid format errors
|
|
65
68
|
"""
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
69
|
+
logger.info(f"Cleaning PDF buffer...")
|
|
70
|
+
file_data.seek(0)
|
|
71
|
+
process = subprocess.Popen(
|
|
72
|
+
["/usr/bin/pdftocairo", "-pdf", "-", "-"],
|
|
73
|
+
stdin=subprocess.PIPE,
|
|
74
|
+
stdout=subprocess.PIPE,
|
|
75
|
+
)
|
|
76
|
+
output = process.communicate(input=file_data.read())[0]
|
|
77
|
+
result = BytesIO()
|
|
78
|
+
result.write(output)
|
|
79
|
+
result.seek(0)
|
|
80
|
+
return result
|
|
81
|
+
|
|
82
|
+
def _get_pdf_stamp(self, display_stamp: bool) -> TextStampStyle:
|
|
83
|
+
"""
|
|
84
|
+
Prepare physical stamp to apply on the PDF
|
|
85
|
+
|
|
86
|
+
:param bool display_stamp: Whether the stamp must be visible or not
|
|
87
|
+
|
|
88
|
+
:return TextStampStyle: The stamp object
|
|
89
|
+
"""
|
|
90
|
+
stamp = None
|
|
91
|
+
if display_stamp:
|
|
92
|
+
stamp = TextStampStyle(
|
|
93
|
+
timestamp_format="%d/%m/%Y %H:%M:%S %Z",
|
|
94
|
+
stamp_text="Signé par: %(signer)s\nLe: %(ts)s",
|
|
95
|
+
border_width=2,
|
|
96
|
+
)
|
|
97
|
+
else:
|
|
98
|
+
stamp = TextStampStyle(
|
|
99
|
+
stamp_text="",
|
|
100
|
+
border_width=0,
|
|
101
|
+
)
|
|
102
|
+
return stamp
|
|
73
103
|
|
|
74
104
|
def sign(
|
|
75
105
|
self, pdf_data: FileData, node_id: int = None, with_stamp: bool = False
|
|
@@ -80,7 +110,8 @@ class SignPDFService(object):
|
|
|
80
110
|
|
|
81
111
|
:param FileData pdf_data: The FileData object describing the PDF file
|
|
82
112
|
:param int node_id: The related node's id if relevant
|
|
83
|
-
:param bool with_stamp:
|
|
113
|
+
:param bool with_stamp: Whether we want a printed stamp on result file or not
|
|
114
|
+
|
|
84
115
|
:return bool: either the PDF has been signed or not
|
|
85
116
|
"""
|
|
86
117
|
|
|
@@ -88,7 +119,7 @@ class SignPDFService(object):
|
|
|
88
119
|
|
|
89
120
|
# Check mimetype
|
|
90
121
|
if not pdf_data.mimetype == "application/pdf":
|
|
91
|
-
logger.
|
|
122
|
+
logger.warning("File is not a PDF, signing aborted")
|
|
92
123
|
return False
|
|
93
124
|
|
|
94
125
|
# Load sign certificate
|
|
@@ -103,26 +134,18 @@ class SignPDFService(object):
|
|
|
103
134
|
)
|
|
104
135
|
raise Exception(ERROR_LOAD_CERTIFICATE_MSG)
|
|
105
136
|
|
|
106
|
-
#
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
border_width=2,
|
|
113
|
-
)
|
|
114
|
-
else:
|
|
115
|
-
stamp = TextStampStyle(
|
|
116
|
-
stamp_text="",
|
|
117
|
-
border_width=0,
|
|
118
|
-
)
|
|
137
|
+
# Clean PDF
|
|
138
|
+
try:
|
|
139
|
+
pdf_data.data = self._get_clean_pdf(pdf_data.data)
|
|
140
|
+
except Exception as error:
|
|
141
|
+
logger.error(f"Error while cleaning original PDF file : {error}")
|
|
142
|
+
self.sign(pdf_data, node_id, with_stamp, as_image=True)
|
|
119
143
|
|
|
120
|
-
# Open
|
|
144
|
+
# Open PDF
|
|
121
145
|
try:
|
|
122
|
-
pdf_data.data = self._get_safe_pdf(pdf_data.data)
|
|
123
146
|
pdf_writer = IncrementalPdfFileWriter(pdf_data.data, strict=False)
|
|
124
147
|
except Exception as error:
|
|
125
|
-
logger.error(f"Error while opening
|
|
148
|
+
logger.error(f"Error while opening PDF file : {error}")
|
|
126
149
|
raise HTTPUnsupportedMediaType(ERROR_PDF_FORMAT_MSG)
|
|
127
150
|
|
|
128
151
|
# Add signature field on the PDF
|
|
@@ -134,8 +157,11 @@ class SignPDFService(object):
|
|
|
134
157
|
),
|
|
135
158
|
)
|
|
136
159
|
except SigningError:
|
|
137
|
-
logger.
|
|
160
|
+
logger.warning("File is already signed, nothing to do")
|
|
138
161
|
return True
|
|
162
|
+
except Exception as error:
|
|
163
|
+
logger.error(f"Error while adding signature field : {error}")
|
|
164
|
+
raise HTTPUnsupportedMediaType(ERROR_PDF_FORMAT_MSG)
|
|
139
165
|
|
|
140
166
|
# Sign PDF
|
|
141
167
|
try:
|
|
@@ -143,12 +169,14 @@ class SignPDFService(object):
|
|
|
143
169
|
pdf_signer = signers.PdfSigner(
|
|
144
170
|
meta,
|
|
145
171
|
signer=signer,
|
|
146
|
-
stamp_style=
|
|
172
|
+
stamp_style=self._get_pdf_stamp(with_stamp),
|
|
147
173
|
)
|
|
148
174
|
pdf_data.data = pdf_signer.sign_pdf(pdf_writer)
|
|
149
175
|
except Exception as error:
|
|
150
176
|
logger.error(f"Error while signing PDF file : {error}")
|
|
151
177
|
raise HTTPUnsupportedMediaType(ERROR_PDF_FORMAT_MSG)
|
|
178
|
+
|
|
179
|
+
# Success
|
|
152
180
|
logger.info(
|
|
153
181
|
"File '{}' signed successfully by {} !".format(
|
|
154
182
|
pdf_data.name, signer.subject_name
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: caerp-sign-pdf
|
|
3
|
-
Version: 2024.
|
|
3
|
+
Version: 2024.2.0
|
|
4
4
|
Summary: caerp_sign_pdf
|
|
5
5
|
Home-page: https://framagit.org/caerp/caerp_sign_pdf
|
|
6
6
|
Author: Kilya
|
|
7
7
|
Author-email: contact@kilya.net
|
|
8
8
|
License: GPLv3
|
|
9
9
|
Keywords: web wsgi bfg pylons pyramid caerp
|
|
10
|
+
Platform: UNKNOWN
|
|
10
11
|
Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
|
|
11
12
|
Classifier: Programming Language :: Python
|
|
12
13
|
Classifier: Framework :: Pyramid
|
|
@@ -69,3 +70,5 @@ Sous linux la signature d'un document PDF peut être vérifiée facilement en li
|
|
|
69
70
|
|
|
70
71
|
pdfsig <monfichierpdf.pdf>
|
|
71
72
|
|
|
73
|
+
|
|
74
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
pyHanko[image-support,opentype,pkcs11,xmp]==0.25.1
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
2024.1.3
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
pyHanko[pkcs11,image-support,opentype,xmp]==0.25.0
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
pyHanko[image-support,opentype,pkcs11,xmp]==0.25.0
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{caerp_sign_pdf-2024.1.3 → caerp_sign_pdf-2024.2.0}/src/caerp_sign_pdf.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
{caerp_sign_pdf-2024.1.3 → caerp_sign_pdf-2024.2.0}/src/caerp_sign_pdf.egg-info/not-zip-safe
RENAMED
|
File without changes
|
{caerp_sign_pdf-2024.1.3 → caerp_sign_pdf-2024.2.0}/src/caerp_sign_pdf.egg-info/top_level.txt
RENAMED
|
File without changes
|