Add support for parsing password-protected PDFs

Thanks to @nikhilbhawsinka for raising the question in
https://github.com/jsvine/pdfplumber/issues/101

Test PDF via https://www.novapdf.com/pdf-example-files-created-with-novapdf-kb.html
This commit is contained in:
Jeremy Singer-Vine
2019-04-14 23:02:57 -04:00
parent b186653802
commit 6f70d0937a
4 changed files with 16 additions and 2 deletions
+2
View File
@@ -65,6 +65,8 @@ with pdfplumber.open("path/to/file.pdf") as pdf:
Both methods return an instance of the `pdfplumber.PDF` class. Both methods return an instance of the `pdfplumber.PDF` class.
To load a password-protected PDF, pass the `password` keyword argument, e.g., `pdfplumber.open("file.pdf", password = "test")`.
### The `pdfplumber.PDF` class ### The `pdfplumber.PDF` class
The top-level `pdfplumber.PDF` class represents a single PDF and has two main properties: The top-level `pdfplumber.PDF` class represents a single PDF and has two main properties:
+8 -2
View File
@@ -13,13 +13,19 @@ from pdfminer.psparser import PSLiteral
class PDF(Container): class PDF(Container):
cached_properties = Container.cached_properties + [ "_pages" ] cached_properties = Container.cached_properties + [ "_pages" ]
def __init__(self, stream, pages=None, laparams=None, precision=0.001): def __init__(self,
stream,
pages = None,
laparams = None,
precision = 0.001,
password = b""
):
self.laparams = None if laparams == None else LAParams(**laparams) self.laparams = None if laparams == None else LAParams(**laparams)
self.stream = stream self.stream = stream
self.pages_to_parse = pages self.pages_to_parse = pages
self.precision = precision self.precision = precision
rsrcmgr = PDFResourceManager() rsrcmgr = PDFResourceManager()
self.doc = PDFDocument(PDFParser(stream)) self.doc = PDFDocument(PDFParser(stream), password = password)
self.metadata = {} self.metadata = {}
for info in self.doc.info: for info in self.doc.info:
self.metadata.update(info) self.metadata.update(info)
Binary file not shown.
+6
View File
@@ -50,3 +50,9 @@ class Test(unittest.TestCase):
assert(rotated.pages[0].cropbox == self.pdf.pages[0].cropbox) assert(rotated.pages[0].cropbox == self.pdf.pages[0].cropbox)
assert(rotated.pages[0].bbox != self.pdf.pages[0].bbox) assert(rotated.pages[0].bbox != self.pdf.pages[0].bbox)
def test_password(self):
path = os.path.join(HERE, "pdfs/password-example.pdf")
pdf = pdfplumber.open(path, password = "test")
assert(len(pdf.chars) > 0)
pdf.close()