Find a Europass CV's attachment without its optional /Type marker (#318) #1183

Merged
tiagoagueda merged 1 commit from 318-europass-real-download into main 2026-10-31 19:00:41 +00:00
Owner

plugins/europass/pdf.py found a CV's attachment only through a stream marked /Type /EmbeddedFile, which the PDF specification makes optional. A real Candidate XML in a PDF without that marker (Google Docs wrapper, /UF only) was refused with "That PDF has nothing attached to it".

What the reader does now:

  • It also follows each file specification's /EF to the stream it names, even with no /Type.
  • When nothing else is found, it looks inside object streams. That is capped at 16, within the 5 MB attachment cap.
  • An attachment reached several ways is read once.
  • /F, /UF or a server path, and the name tree, /AF or both, all work.
  • Nothing is fetched, and the existing caps on markers and attachments still apply.

Tests (271 passed):

  • test_a_real_download_reads runs over tests/data/europass-vatanasov/test_with_attachment.pdf. That is a real current-editor Candidate XML (MIT, invented data, provenance and licence in its README) inside a Google Docs PDF.
  • The October-2026 editor shape (/Subtype /text/xml, Flate, /AF) is tested across 24 naming and listing cases.
  • 16 cases with and without /Type and /Subtype.
  • Guards: one attachment read once, an /EF that points at nothing, and object streams opened only so far.

A genuine editor PDF (a real person's CV, not committed) was read locally and checked by its counts.

Refs #318. The issue still needs a CV that the maintainer downloads from the editor.

🤖 Generated with Claude Code

`plugins/europass/pdf.py` found a CV's attachment only through a stream marked `/Type /EmbeddedFile`, which the PDF specification makes optional. A real `Candidate` XML in a PDF without that marker (Google Docs wrapper, `/UF` only) was refused with "That PDF has nothing attached to it". **What the reader does now:** - It also follows each file specification's `/EF` to the stream it names, even with no `/Type`. - When nothing else is found, it looks inside object streams. That is capped at 16, within the 5 MB attachment cap. - An attachment reached several ways is read once. - `/F`, `/UF` or a server path, and the name tree, `/AF` or both, all work. - Nothing is fetched, and the existing caps on markers and attachments still apply. **Tests (271 passed):** - `test_a_real_download_reads` runs over `tests/data/europass-vatanasov/test_with_attachment.pdf`. That is a real current-editor `Candidate` XML (MIT, invented data, provenance and licence in its README) inside a Google Docs PDF. - The October-2026 editor shape (`/Subtype /text/xml`, Flate, `/AF`) is tested across 24 naming and listing cases. - 16 cases with and without `/Type` and `/Subtype`. - Guards: one attachment read once, an `/EF` that points at nothing, and object streams opened only so far. A genuine editor PDF (a real person's CV, not committed) was read locally and checked by its counts. Refs #318. The issue still needs a CV that the maintainer downloads from the editor. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Read a Europass PDF's attachment when its stream is not marked as one (#318)
All checks were successful
CI / Unit tests and coverage (Python 3.14) (pull_request) Successful in 15m20s
CI / Checks: lint, migrations, catalogues, settings, built files (pull_request) Successful in 1m28s
CI / Database tests on PostgreSQL (pull_request) Successful in 3m29s
CI / Security audit (pull_request) Successful in 53s
CI / Browser tests (Chromium) (pull_request) Successful in 36m55s
68840facbf
The PDF reader found an attached CV only by a stream saying /Type /EmbeddedFile, which ISO
32000-1 makes optional. A real Candidate XML attached by Google Docs (vatanasov/cv, MIT,
now tests/data/europass-vatanasov) is a bare stream reached from /EmbeddedFiles, so the
reader said the PDF had nothing attached. It now also follows each file specification's
/EF to the stream it names, found by its object header; and, only when nothing else is
found, looks for the file specification inside the object streams, at most 16 and
unpacking no more between them than the attachment cap. A stream reached two ways is read
once.

Tests: test_a_real_download_reads over that file, and built PDFs for the October 2026
shape (/Subtype /text/xml, Flate, /AF; named by /F, /UF or a server path; listed in the
tree, /AF or both; plain or with object streams) and for attachments with or without
/Type and /Subtype, stored or compressed.

Refs #318

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
tiagoagueda force-pushed 318-europass-real-download from 68840facbf
All checks were successful
CI / Unit tests and coverage (Python 3.14) (pull_request) Successful in 15m20s
CI / Checks: lint, migrations, catalogues, settings, built files (pull_request) Successful in 1m28s
CI / Database tests on PostgreSQL (pull_request) Successful in 3m29s
CI / Security audit (pull_request) Successful in 53s
CI / Browser tests (Chromium) (pull_request) Successful in 36m55s
to a6405ec913
All checks were successful
CI / Unit tests and coverage (Python 3.14) (pull_request) Successful in 14m22s
CI / Checks: lint, migrations, catalogues, settings, built files (pull_request) Successful in 1m27s
CI / Database tests on PostgreSQL (pull_request) Successful in 3m30s
CI / Security audit (pull_request) Successful in 42s
CI / Browser tests (Chromium) (pull_request) Successful in 35m10s
2026-10-31 18:59:06 +00:00
Compare
tiagoagueda deleted branch 318-europass-real-download 2026-10-31 19:00:41 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
Postulo/postulo!1183
No description provided.