PhpNative engine: non-ASCII characters in the signature stamp are rendered as mojibake
I maintainer di solito rispondono entro 1 giorno
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 4/5
- Tempo stimato
- 3-5 giorni
- Idoneità per principianti
- 56/100
Direzione di ricerca
Inizia in lib/Handler/SignEngine/PhpNativeHandler.php, leggendo escapePdfText() intorno alla riga 398 e il dizionario dei font intorno alla riga 336. Riproduci il problema con il template francese fornito, quindi confronta il percorso di rendering PhpNative con JSignPdf. Il lavoro è completato quando il timbro visibile preserva il testo non-ASCII supportato e gestisce i caratteri al di fuori di tale intervallo senza mojibake silenzioso.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
Describe the bug
With the PhpNative signature engine, non-ASCII characters in the visible signature stamp are
rendered as mojibake. The stored signature_text_template is correct — the corruption happens at
render time.
A French template produced this on the signed PDF:
| Template (stored, correct) | Rendered in the PDF |
|---|---|
Signé avec LibreSign |
Sign^ avec LibreSign |
Émetteur : Phenix Tech |
^ metteur : Phenix Tech |
To reproduce
- Set
signature_enginetoPhpNative. - Set a
signature_text_templatecontaining accented characters, e.g.
Signé avec LibreSign\n{{SignerCommonName}}\nÉmetteur : {{IssuerCommonName}}. - Sign a document and open the result — the accented characters are mangled.
occ config:app:get libresign signature_text_template still returns the correct UTF-8, confirming
the problem is in the rendering path and not in storage.
Expected behavior
The visible stamp should render the template as stored, at least for the Latin-1 range.
Root cause
Two things combine in lib/Handler/SignEngine/PhpNativeHandler.php:
1. No encoding conversion. escapePdfText() (line 398) only escapes PDF delimiters:
private function escapePdfText(string $value): string {
$value = str_replace('\\', '\\\\', $value);
$value = str_replace('(', '\\(', $value);
$value = str_replace(')', '\\)', $value);
return $value;
}
The raw UTF-8 bytes are then written straight into a PDF literal string via
sprintf("(%s) Tj\n", $escaped). é (0xC3 0xA9) therefore reaches the content stream as two
separate byte codes.
2. A single-byte base font with no declared encoding (line 336):
resources: [
'Font' => [
'F1' => [
'Type' => '/Font',
'Subtype' => '/Type1',
'BaseFont' => '/Helvetica',
],
],
],
There is no /Encoding entry, so the viewer falls back to Helvetica's built-in StandardEncoding.
Each UTF-8 byte is mapped independently, which is exactly the observed output.
Possible directions
- Minimal: convert the string to WinAnsi and declare
/Encoding /WinAnsiEncodingin the font
dictionary. Covers Latin-1, so most Western European templates, and is a small change. Characters
outside Latin-1 would still need a fallback rather than silent corruption. - Complete: embed a TrueType subset with a proper
/Encoding(or a Type0/Identity-H font) to
support the full Unicode range, at the cost of a larger PDF and a font to ship.
Either way, it would be worth failing loudly — or transliterating explicitly — rather than emitting
bytes that render as mojibake, since the result lands on a signed document that cannot be corrected
afterwards without invalidating the signature.
Why this matters more than it looks
This is engine-specific: JSignPdf renders the same template correctly through iText. The two
engines are therefore not interchangeable in both directions.
It compounds with #8145: JSignPdf currently cannot timestamp against any TSA that rejects SHA-1,
so instances that need RFC 3161 timestamping are pushed towards PhpNative — and there they must
restrict their signature stamp to ASCII. Right now there is no engine that does both correct
timestamping and correct non-ASCII rendering.
Workaround
Restrict signature_text_template to ASCII. In French this is doable with some care — Signature,
Certificat, Date carry no accents — but it constrains the wording, and nothing warns the
administrator that the template will be corrupted.
Environment
- LibreSign 13.3.0
- Nextcloud 33.0.8 (All-in-One)
- Signature engine:
PhpNative(jeidison/signer-php) - Certificate engine: OpenSSL, self-signed internal root CA
- Lingua principale
- PHP
- Stelle
- 818
- Fork
- 146
- Merge medio
- 6h 48m
- PR unite (30g)
- 622
Preparare l'ambiente
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di LibreSign/libresign
-
good first issue
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
LibreSign/libresign#8284 · 5 commenti ·
I maintainer di solito rispondono entro 1 giorno
-
backend enhancement php
Difficoltà 4/5 3-5 giorni Idoneità per principianti 68/100
I maintainer di solito rispondono entro 1 giorno
-
backend enhancement php
Difficoltà 5/5 Più di una settimana Idoneità per principianti 35/100
I maintainer di solito rispondono entro 1 giorno
-
backend php
Difficoltà 4/5 3-5 giorni Idoneità per principianti 48/100
I maintainer di solito rispondono entro 1 giorno
-
frontend javascript
Difficoltà 4/5 3-5 giorni Idoneità per principianti 48/100
I maintainer di solito rispondono entro 1 giorno
Tutte le issue di LibreSign/libresign
Issue simili
-
sync-en
Difficoltà 2/5 1-3 ore Idoneità per principianti 76/100
I maintainer di solito rispondono entro 1 giorno
-
bug Feature: Kiosk
Difficoltà 2/5 1-3 ore Idoneità per principianti 76/100
I maintainer di solito rispondono entro 1 giorno
-
Infrastructure: actions Module: zmscitizenapi Module: zmsentities php Type: Bug unit tests
Difficoltà 2/5 1-3 ore Idoneità per principianti 88/100
it-at-m/eappointment#3480 ·
I maintainer di solito rispondono entro 1 giorno
-
HttpClient
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100
I maintainer di solito rispondono entro 1 giorno
-
CI: composer install fails — league/flysystem 1.x blocked by security advisory GHSA-cxf4-7mrp-vvprApertadevops type: bug
Difficoltà 2/5 1-3 ore Idoneità per principianti 84/100
I maintainer di solito rispondono entro 1 giorno