Skip to content

Feat/support jsignpdf 3 - #59

Open
YvesCesar wants to merge 15 commits into
mainfrom
feat/support-jsignpdf-3
Open

Feat/support jsignpdf 3#59
YvesCesar wants to merge 15 commits into
mainfrom
feat/support-jsignpdf-3

Conversation

@YvesCesar

@YvesCesar YvesCesar commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Related issue #52

Updates the wrapper to the current stable JSignPdf (3.1.0) and keeps every password out of the command line.

CLI differences between 2.3 and 3.1

Change What it required here
Passwords can be read from stdin since 3.0.0: --enable-stdin-passwords plus - as the option value, read one line each in the fixed order -ksp, -kp, -opwd, -upwd, -tscp, -tsp signing moved from exec() to proc_open(), writing the passwords to stdin
The fat jar was dropped in 3.1; the ZIP ships a lib/ directory start from the classpath (com.intoolswetrust.jsignpdf.Bootstrap), keeping -jar as a fallback for 3.0.x
Default hash algorithm is now SHA-256 documented; it needs at least a PDF-1.6
The CLI appends the signature by default; --overwrite was added and -a kept as a no-op documented; example/index.php now passes --overwrite
--version output and the Finished: Signature succesfully created. message unchanged, so the parsing was kept as it was

What changed

  • Every value reaching the shell goes through escapeshellarg(): the java binary, the jar or classpath, the PDF, -ksf and -d.

  • No password is passed as an argument any more. Besides setPassword(), the key, owner, user and TSA passwords have their own setters and are sent through stdin:

    $param->setTsaPassword('tsa password');

Passing them to setJSignParameters() as a list works too — the value is taken out of the command line just the same.

  • setJSignParameters() accepts a list of options and values, which the package escapes.
  • The installer downloads to a staging directory and replaces the previous install instead of merging into it, so upgrades don't leave a stale jar behind.
  • The default download URL is now jsignpdf-3.1.0-minimal.zip.

Compatibility

  • JSignPdf 2.x is no longer supported: it has no way to read passwords from stdin. Pointing setJSignPdfDownloadUrl() or setjSignPdfJarPath() at a 2.x release stops working. JSignPdf 3.x needs a Java 21+ runtime.
  • Signing a PDF older than 1.6 with the default parameters now fails, because SHA-256 needs PDF-1.6 and the append mode cannot upgrade the PDF version. Use --overwrite or a hash algorithm the PDF version supports.
  • The string form of setJSignParameters() is still passed through unparsed, so a password written there does reach the command line. The README points to the setters and to the list form instead.

Testing

  • Unit tests for version detection, successful signing, signing errors, paths with spaces and quotes, option values with shell metacharacters, the order of the passwords on stdin, both distribution layouts and the installer upgrade paths.
  • A new integration group runs the real JSignPdf — version, signing, visible signature with page and coordinates, explicit hash algorithm, more than one password on stdin, and the pre-1.6 failure. It runs in its own CI job and is excluded from test:unit and from coverage.

Signed-off-by: YvesCesar <yvesamorim73@gmail.com>
Signed-off-by: YvesCesar <yvesamorim73@gmail.com>
Signed-off-by: YvesCesar <yvesamorim73@gmail.com>
Signed-off-by: YvesCesar <yvesamorim73@gmail.com>
@YvesCesar
YvesCesar marked this pull request as draft September 1, 2026 19:46
Signed-off-by: YvesCesar <yvesamorim73@gmail.com>
Signed-off-by: YvesCesar <yvesamorim73@gmail.com>
…ration group

Signed-off-by: YvesCesar <yvesamorim73@gmail.com>
Signed-off-by: YvesCesar <yvesamorim73@gmail.com>
Signed-off-by: YvesCesar <yvesamorim73@gmail.com>
Signed-off-by: YvesCesar <yvesamorim73@gmail.com>
@YvesCesar
YvesCesar marked this pull request as ready for review September 2, 2026 14:11
Comment thread src/Sign/JSignParam.php Outdated
Comment thread .github/workflows/phpunit.yml
Comment thread src/Sign/JSignService.php
Comment thread src/Sign/JSignParam.php Outdated
Comment thread src/Sign/JSignParam.php Outdated
Comment thread src/Sign/JSignService.php Outdated
…stant

Signed-off-by: YvesCesar <yvesamorim73@gmail.com>
… path

Signed-off-by: YvesCesar <yvesamorim73@gmail.com>
…meters

Signed-off-by: YvesCesar <yvesamorim73@gmail.com>
… a plain executable

Signed-off-by: YvesCesar <yvesamorim73@gmail.com>
Signed-off-by: YvesCesar <yvesamorim73@gmail.com>
Comment thread src/Sign/JSignParam.php
* @param list<string> $parameters
* @return list<string>
*/
private function takePasswords(array $parameters): array

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think - should be handled as a real password when it comes from the PHP API.

Today takePasswords() treats - in a special way and keeps it in the command line. Then JSignPdf receives -tsp - and waits for one more password from stdin, but the wrapper does not store or send this value.

Now the wrapper controls the stdin password handling, so the caller should not need to know about the JSignPdf - special value.

Maybe takePasswords() can always save the password value, including -.

For example, both cases:

['-tsp', '-']
['-tsp=-']

can mean that the real TSA password is -.

The wrapper can still generate:

-tsp -

and send - in the correct stdin position.

It would also be good to update the current test and cover both cases.

Comment thread src/Sign/JSignService.php
Comment on lines 79 to 87
public function getVersion(JSignParam $params): string
{
$java = $this->javaCommand($params);
$jSignPdf = $this->getjSignPdfJarPath($params);
$jSignPdf = $params->getjSignPdfJarPath();
$java = escapeshellarg($this->javaCommand($params));
$jSignPdf = $this->jSignPdfInvocation($params);

$command = "$java -jar $jSignPdf --version 2>&1";
$command = implode(' ', array_merge([$java], $this->javaOptions($params), [$jSignPdf, '--version'])) . ' 2>&1';
exec($command, $output);
$lastRow = end($output);
if (empty($output) || strpos($lastRow, 'version') === false) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

getVersion() also runs JSignPdf, but it does not use the environment configured with setEnvironmentVariables().

The signing path correctly passes these variables through proc_open(), while the version path still uses exec().

I suggest using the same process execution mechanism for both operations, so Java options and environment variables have the same behavior whenever this package runs JSignPdf.

This is especially relevant for externally managed installations such as LibreSign, where JSIGNPDF_HOME is explicitly configured.

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.

2 participants