Skip to content

Conversation

@iamrishu11
Copy link

@iamrishu11 iamrishu11 commented Oct 15, 2025

Fixes #19

Description

What’s new

  • pdfly meta now shows a compact, single-line Permissions field in the PDF Data table.
  • Unencrypted PDFs show n/a (unencrypted).
  • Encrypted PDFs show a comma-separated list of the allowed permissions (e.g., print, modify, annotate, fill-forms).
    If none are allowed, it shows none (all denied).

Why

How

  • Uses PdfReader.user_access_permissions from pypdf.
  • New helper _format_permissions(...)
  • Also fixes header reading for encrypted PDFs by seeking to position 0 before reading the %PDF-… version.

Tests

  • Manual verification included (screenshots in this PR)

For an encrypted pdf

image

For a normal file

image

Notes

  • Output order of permissions is alphabetical for stability.

Checklist:

  • A unit test is covering the code added / modified by this PR

  • In case of a new feature, docstrings have been added, with also some documentation in the docs/ folder

  • A mention of the change is present in CHANGELOG.md

  • This PR is ready to be merged

By submitting this pull request, I confirm that my contribution is made under the terms of the BSD 3-Clause license.

Copy link
Member

@Lucas-C Lucas-C left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks really great!

There are those items in the PR checklist that you need to add though:

  • Unit tests for all 2 possible cases: unencrypted & encrypted
  • A mention of the new feature added to CHANGELOG.md

@Lucas-C Lucas-C changed the title meta: add Permissions + fix version read on encrypted; tidy Encrypted… ENH: meta command - Add Permissions + fix version read on encrypted PDFs Oct 15, 2025
@Lucas-C
Copy link
Member

Lucas-C commented Oct 15, 2025

I'm not sure if this 2nd table visible in your screenshot is needed, given that the same information is visible in the 1st table:
img

@iamrishu11
Copy link
Author

alr, removing the diff table and adding unittest and changelogs

@iamrishu11
Copy link
Author

Quick sanity check on the test fixture paths

I’m planning to use the following in the tests:

from pathlib import Path

rel = Path("sample-files/002-trivial-libre-office-writer/002-trivial-libre-office-writer.pdf")
input_pdf = RESOURCES_ROOT / rel

Assuming RESOURCES_ROOT points to the repo root (as in tests/conftest.py), this resolves to:

/sample-files/002-trivial-libre-office-writer/002-trivial-libre-office-writer.pdf

…which is the expected location in the sample-files submodule. If RESOURCES_ROOT already points inside sample-files/, I’ll drop the leading sample-files/ from rel.

The test also pytest.skip(...)s if the file isn’t present, and the submodule can be initialized with:

git submodule update --init --recursive

Shout if you prefer me to reference it as:

rel = Path("002-trivial-libre-office-writer/002-trivial-libre-office-writer.pdf")
input_pdf = RESOURCES_ROOT / "sample-files" / rel

Either style works; just want to match the project’s convention.

@Lucas-C
Copy link
Member

Lucas-C commented Oct 15, 2025

Quick sanity check on the test fixture paths
[...]
Either style works; just want to match the project’s convention.

Let's got for this:

SAMPLE_FILES = RESOURCES_ROOT / "sample-files"
input_pdf = SAMPLE_FILES / rel

assert "permissions" in metadata
perms = metadata["permissions"]
assert perms not in {"n/a (unencrypted)", "unknown"}
# If not "all denied", check formatting invariants
Copy link
Member

@Lucas-C Lucas-C Oct 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be known, given that we test a specific PDF file, right?

Maybe it would be better to have 2 distinct test cases/methods:

  • one that checks that none (all denied) is displayed
  • one that checks that the expected permissions are displayed

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so instead of running that test on only those two file i can run that on all the files in the sample-files/, would that be cool?

Copy link
Member

@Lucas-C Lucas-C Oct 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That would be cool, yes.
However I tested your code, and the assert act_set == exp_set assertion is never evaluated.
Which means that we don't have any test covering this case...

With which PDF test file have you been able to test pdfly meta behaviour, where it displays a list of permissions?

Copy link
Author

@iamrishu11 iamrishu11 Oct 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right, it seems like the test case isn't fully covered, and I don't have a PDF with the permissions metadata behavior to fully test it yet. I tried generating a sample PDF with permissions using PyPDF2, but I wasn't able to achieve the desired result. Honestly, I don't have a lot of experience with unittest and pytest yet, so I'm still getting familiar with some of the testing patterns. If you have any advice or pointers on how to create or detect PDFs with specific permissions metadata, it would be really helpful!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sample-files/005-libreoffice-writer-password/libreoffice-writer-password.pdf has some permissions set:

$ qpdf --show-encryption sample-files/005-libreoffice-writer-password/libreoffice-writer-password.pdf --password=openpassword
R = 3
P = -1028
User password = openpassword
Supplied password is user password
extract for accessibility: allowed
extract for any purpose: allowed
print low resolution: allowed
print high resolution: allowed
modify document assembly: not allowed
modify forms: allowed
modify annotations: allowed
modify other: allowed
modify anything: not allowed

So there is probably an issue somewhere in the code...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe the password need to be provided to read the permissions, as with qpdf?

@Lucas-C
Copy link
Member

Lucas-C commented Oct 15, 2025

I made a final feedback comment, but appart from that everything looks really good! 👍

I'll merge your PR once you have addressed that last point and the CI pipeline is passing.

@iamrishu11
Copy link
Author

iamrishu11 commented Oct 16, 2025

Hey lucas, can u check now?

@Lucas-C
Copy link
Member

Lucas-C commented Oct 16, 2025

The unit tests are failing:

ERROR tests/test_metadata.py - ValueError: tests/test_metadata.py::test_meta_command_on_all_sample_pdfs: error raised while trying to determine id of parameter 'input_pdf' at position 0

Co-authored-by: Lucas Cimon <[email protected]>
@Lucas-C
Copy link
Member

Lucas-C commented Oct 27, 2025

Hi @iamrishu11 🙂 👋
We are close to the end of the month, I was just curious to know if you were willing to finish this PR as part of Hacktoberfest?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feature request: display pdf permissions in pdfly meta output

2 participants