Skip to content

[stable33] feat: Sign usign only PHP#7073

Merged
vitormattos merged 45 commits intostable33from
backport/2595/stable33
Mar 4, 2026
Merged

[stable33] feat: Sign usign only PHP#7073
vitormattos merged 45 commits intostable33from
backport/2595/stable33

Conversation

@backportbot-libresign
Copy link

@backportbot-libresign backportbot-libresign bot commented Mar 4, 2026

Backport of #2595

Warning, This backport's changes differ from the original and might be incomplete ⚠️

Todo

  • Review and resolve any conflicts

Learn more about backports at https://docs.nextcloud.com/server/stable/go.php?to=developer-backports.

vitormattos and others added 30 commits March 4, 2026 23:01
Signed-off-by: Vitor Mattos <vitor@php.rio>
Signed-off-by: Vitor Mattos <vitor@php.rio>
Signed-off-by: Vitor Mattos <vitor@php.rio>
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
- Reduce line height from 1.2× to 1.15× font size for tighter spacing
- Set top padding to 0.35× line height to match JSignPdf output
- Ensures visual parity with JSignPdf's iText-based text rendering

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
- Replace string literal 'GRAPHIC_ONLY' with SignerElementsService::RENDER_MODE_GRAPHIC_ONLY
- Improves code consistency and maintainability

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
- Use date_default_timezone_get() instead of hardcoded UTC
- Ensures ServerSignatureDate reflects actual server timezone configuration
- Captures date at rendering time, not during params preparation

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
- ServerSignatureDate is now injected at rendering time by each handler
- PhpNativeHandler uses server timezone
- JSignPdfHandler uses ${timestamp} placeholder
- Ensures proper timezone handling for each implementation

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
- LocalSignerSignatureDateTime now uses user's timezone, not UTC
- Correctly reflects 'Local' in variable name
- Use date_default_timezone_get() for user's configured timezone
- LocalSignerTimezone parameter indicates which timezone was used

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
…ervice

- Replace string literal 'GRAPHIC_ONLY' with SignerElementsService::RENDER_MODE_GRAPHIC_ONLY
- Add SignerElementsService import
- Improves code consistency across codebase

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
- New render mode for PhpNativeHandler to show signature without description text
- Full canvas displays signature drawing with watermark background
- Extends existing JSignPdf render modes for PHP-only signing

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
…bject text operators

Remove Imagick/ITempManager dependencies from PhpNativeHandler. All render modes now produce a SignatureAppearanceXObjectDto carrying PDF text stream operators instead of compositing raster images. The paradoxical-condition psalm issue is also resolved here - the max(0.0,...) guard was removed so the inner overflow check can fire.

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
…pearance branch

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Covers: wrapTextForPdf (4 cases), escapePdfText (5 cases), hasExistingSignatures (5 cases), buildTimestampOptions (4 cases), resolveCertificationLevel (4 cases), buildAppearanceForElement signature image placement (2 cases), buildXObject layout per render mode (4 cases).
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
…signature params

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
…x-start

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
…re without placed elements

When admin sets GRAPHIC_ONLY render mode (canCreateSignature=true), the signer
must draw their signature even if no visual element box was placed on the
document. The previous check required visibleElements.some(...) which returned
false for documents with no placed boxes, silently skipping the drawing prompt.

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
… elements

needsCreateSignature previously required visibleElements.some(...) to be true,
meaning it only triggered when the document had a pre-placed visual element box
for the signer. With GRAPHIC_ONLY render mode (canCreateSignature=true) and no
placed box, the check always returned false and the drawing prompt was never
shown.

Fix: when signerHasSignRequest=true is provided, return true immediately after
confirming the signer has a signRequestId — the visual box placement is
irrelevant for deciding whether to ask for a drawing.

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
…ement

needCreateSignature computed was duplicating the validator logic and also
required a placed visual element box, so it returned false for clickToSign
documents in GRAPHIC_ONLY mode.

Added signerHasSignRequest computed (true when the current user has a
signRequestId) and pass it to requirementValidator.getFirstUnmetRequirement()
in both confirmSignDocument and executeSigningAction so the validator can
prompt for the signature drawing even when no element box was placed.

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
…image

When canCreateSignature is true but the signer performs a clickToSign
(no drawn image submitted), the DB file element was silently skipped,
producing an empty visibleElements list and no stamp on the document.
Include the element with an empty tempFile so the admin background
image (n0 layer) is still rendered in the signature stamp.

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
…ment

Add case: canCreateSignature=true, signer submits no element but an
admin-placed file element exists. The visibleElements list must still
contain that element (with empty tempFile) so the stamp is rendered.

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
…y image path

When background is present but the signer submitted no image
(clickToSign), passing an empty string to mergeBackgroundWithSignature
caused new Imagick('') to throw. Guard the call: only merge when both
paths are non-empty; fall back to background-only or signature-only
as appropriate. Also skip --img-path entirely when signatureImagePath
is empty in GRAPHIC_AND_DESCRIPTION mode.

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
…background

Add providerSignAffectedParams case: GRAPHIC_AND_DESCRIPTION render
mode with a background image but no user signature (empty imagePath).
Expects --bg-path with background only and no --img-path, verifying
the Imagick crash guard introduced in JSignPdfHandler.

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
…ME alignment

Three fixes:
- useDefaultAppearance: false for invisible signatures (no visibleElements)
  to prevent the pdf-signer-php default stamp from appearing.
- GRAPHIC_ONLY: buildXObject now returns an empty n2 stream immediately,
  preventing description text from leaking into graphic-only stamps.
- GRAPHIC_ONLY: buildAppearanceForElement now assigns the user's drawn
  image to the full bbox (signatureImageFrame=null), fixing blank stamps.
- SIGNAME_AND_DESCRIPTION: signer name is now horizontally centred within
  the left half of the stamp instead of being pinned to leftPadding.

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
…centering

Add three regression tests:
- testBuildXObjectGraphicOnlyReturnsEmptyStream: n2 stream must be empty
  for GRAPHIC_ONLY so no text leaks into graphic-only stamps.
- testBuildAppearanceForElementSetsSignatureImageInGraphicOnlyMode: user
  image must be assigned to the full bbox (signatureImageFrame=null).
- testBuildXObjectSignameAndDescriptionCentersNameInLeftHalf: signer name
  X position must be centred (39.60) not left-aligned (2.00).

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
…acing

JSignPdf renders description text with baseline-to-baseline equal to the
font size (leading factor 1.0).  PhpNative was using 1.2, producing 20%
extra space between lines and a visually inconsistent stamp.  Set the
factor to 1.0 for both the description block and the signer-name block.

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
…ine height

nameStartY = (80 + 20) / 2 - 20 = 30.0  (was 32.0 with old 1.2 factor)
Update expected Td coordinate from 32.00 to 30.00 and fix the doc comment.

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
…s (clickToSign fix)

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
…oid blocking clickToSign

The commit e9ea794 changed needCreateSignature to return true for any
signer with a signRequestId, without checking whether visual elements
were placed. This caused the 'Sign the document.' button to be hidden
in clickToSign scenarios, because the 'Define your signature' prompt
was shown instead.

The signerHasSignRequest flag is already passed to the validator in
confirmSignDocument and executeSigningAction, so the drawing prompt
is triggered at action time when appropriate (e.g. GRAPHIC_ONLY mode).
The upfront needCreateSignature computed should only block the sign
button when there are placed visible elements for this signer.

Fixes E2E tests: multi-signer-sequential, sign-email-token-unauthenticated,
sign-herself-with-click-to-sign

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
…t that bypassed visibleElements check

The shortcut added in e9ea794 caused needsCreateSignature to return true
whenever the signer had a signRequestId, regardless of whether any visual
element box was placed. This silently opened the draw modal for clickToSign
documents with no placed elements.

Remove the shortcut and keep only the visibleElements.some() check,
also normalising signRequestId comparison to String() to be type-safe.

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
…o validator

signerHasSignRequest was added to bypass the visibleElements check in
SigningRequirementValidator, causing the draw modal to open for clickToSign
documents with no placed elements. With the validator fix in place, this
computed and its two call-sites are no longer needed.

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
…se when no visibleElements placed

Corrects the test added in bc17180 that expected true when signerHasSignRequest
was passed; that was testing the (now-removed) broken shortcut. The correct
expectation is false: no placed element means the draw modal must not appear.

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
@vitormattos vitormattos changed the title [stable33] [WIP] Sign usign only PHP [stable33] feat: Sign usign only PHP Mar 4, 2026
@vitormattos vitormattos merged commit 34e64c4 into stable33 Mar 4, 2026
68 of 69 checks passed
@vitormattos vitormattos deleted the backport/2595/stable33 branch March 4, 2026 23:35
@github-project-automation github-project-automation bot moved this from 0. Needs triage to 4. to release in Roadmap Mar 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: 4. to release

Development

Successfully merging this pull request may close these issues.

1 participant