summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornie <nie@odoo.com>2020-11-27 15:56:24 +0000
committernie <nie@odoo.com>2021-01-11 09:07:04 +0000
commit851fe64f7789bb398383c22e3ebbaebb051791f6 (patch)
tree77733d30996f1d3076a2023f253f12058100d91c
parente6ccdb397792db62c3b08d96435b3c1667c1aa9d (diff)
[FIX] tools: try decrypting PDF with empty password
Steps: - Install accounting - On the dashboard, try to upload an "encrypted" PDF like this one https://launchpadlibrarian.net/24827090/DS-0157.pdf Bug: Traceback: PyPDF2.utils.PdfReadError: file has not been decrypted Explanation: In 13.0, these errors were caught in a catch all `except` as shown here: https://github.com/odoo/odoo/blob/4e089041252c25cc197a30f9e285d82f7162d809/addons/account_facturx/models/account_move.py#L303-L328 From this SO comment: https://stackoverflow.com/questions/52047944/pdfbox-extracting-blanks-from-pdf-encrypted-with-no-password#comment91054285_52047944 > A PDF can be encrypted with two passwords: a user password and an owner password. When a PDF is encrypted with a user password, you can't open the document in a PDF viewer without entering that password. When a PDF is encrypted with an owner password only, everyone can open a PDF without that password, but some restrictions may be in place. From time to time, we get a PDF encrypted with an owner password. The content is still readable, but PyPDF2 fails because it thinks the PDF is encrypted. With this fix, we try to unwrap the PDF by providing an empty user password. This way, PyPDF2 thinks the content is now decrypted. However, PyPDF2 only supports decrypting versions 1 and 2 of the encryption implementation. If the version is different, we skip reading the attachments and carry on to allow the user to upload the document. opw:2375993 closes odoo/odoo#62557 Signed-off-by: backspac <backspac@users.noreply.github.com>
-rw-r--r--addons/account_edi/models/account_edi_format.py7
-rw-r--r--odoo/addons/base/tests/test_pdf.py19
-rw-r--r--odoo/tools/pdf.py7
3 files changed, 31 insertions, 2 deletions
diff --git a/addons/account_edi/models/account_edi_format.py b/addons/account_edi/models/account_edi_format.py
index e66338f5ae7..4313e78ddfc 100644
--- a/addons/account_edi/models/account_edi_format.py
+++ b/addons/account_edi/models/account_edi_format.py
@@ -296,8 +296,11 @@ class AccountEdiFormat(models.Model):
return to_process
# Process embedded files.
- for xml_name, content in pdf_reader.getAttachments():
- to_process.extend(self._decode_xml(xml_name, content))
+ try:
+ for xml_name, content in pdf_reader.getAttachments():
+ to_process.extend(self._decode_xml(xml_name, content))
+ except NotImplementedError as e:
+ _logger.warning("Unable to access the attachments of %s. Tried to decrypt it, but %s." % (filename, e))
# Process the pdf itself.
to_process.append({
diff --git a/odoo/addons/base/tests/test_pdf.py b/odoo/addons/base/tests/test_pdf.py
index 6954ca4a689..6f1368e40d0 100644
--- a/odoo/addons/base/tests/test_pdf.py
+++ b/odoo/addons/base/tests/test_pdf.py
@@ -43,6 +43,25 @@ class TestPdf(TransactionCase):
attachments = list(self.minimal_pdf_reader.getAttachments())
self.assertEqual(len(attachments), 2)
+ def test_odoo_pdf_file_reader_with_owner_encryption(self):
+ pdf_writer = pdf.OdooPdfFileWriter()
+ pdf_writer.cloneReaderDocumentRoot(self.minimal_pdf_reader)
+
+ pdf_writer.addAttachment('test_attachment.txt', b'My awesome attachment')
+ pdf_writer.addAttachment('another_attachment.txt', b'My awesome OTHER attachment')
+
+ pdf_writer.encrypt("", "foo")
+
+ with io.BytesIO() as writer_buffer:
+ pdf_writer.write(writer_buffer)
+ encrypted_content = writer_buffer.getvalue()
+
+ with io.BytesIO(encrypted_content) as reader_buffer:
+ pdf_reader = pdf.OdooPdfFileReader(reader_buffer)
+ attachments = list(pdf_reader.getAttachments())
+
+ self.assertEqual(len(attachments), 2)
+
def test_merge_pdf(self):
self.assertEqual(self.minimal_pdf_reader.getNumPages(), 1)
page = self.minimal_pdf_reader.getPage(0)
diff --git a/odoo/tools/pdf.py b/odoo/tools/pdf.py
index 66608c4b1ff..6929e2684ab 100644
--- a/odoo/tools/pdf.py
+++ b/odoo/tools/pdf.py
@@ -77,7 +77,14 @@ PdfFileReader.__init__ = lambda self, stream, strict=True, warndest=None, overwr
class OdooPdfFileReader(PdfFileReader):
# OVERRIDE of PdfFileReader to add the management of multiple embedded files.
+ ''' Returns the files inside the PDF.
+ :raises NotImplementedError: if document is encrypted and uses an unsupported encryption method.
+ '''
def getAttachments(self):
+ if self.isEncrypted:
+ # If the PDF is owner-encrypted, try to unwrap it by giving it an empty user password.
+ self.decrypt('')
+
if not self.trailer["/Root"].get("/Names", {}).get("/EmbeddedFiles", {}).get("/Names"):
return []
for i in range(0, len(self.trailer["/Root"]["/Names"]["/EmbeddedFiles"]["/Names"]), 2):