Hacktoberfest 2026: le issue che i maintainer hanno segnato per ottobre, aperte e adatte ai principianti. Sfoglia le issue Hacktoberfest

PhpNative engine: non-ASCII characters in the signature stamp are rendered as mojibake

Aperta
#8,155 1 commento 0 reazioni 0 assegnatari Vedi su GitHub

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
Tipo di issue
Bug
Chiarezza
Specificata chiaramente
Stato di attività
Attiva
Stack tecnologico
php
Ambito
backend, security

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

backend php
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
  1. Set signature_engine to PhpNative.
  2. Set a signature_text_template containing accented characters, e.g.
    Signé avec LibreSign\n{{SignerCommonName}}\nÉmetteur : {{IssuerCommonName}}.
  3. 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 /WinAnsiEncoding in 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

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di LibreSign/libresign

Tutte le issue di LibreSign/libresign

Issue simili

Altre issue su PHP

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.