Skip to content

Commit 80d1f07

Browse files
committed
feat: fallback to automatic download JSignPdf
Signed-off-by: Vitor Mattos <[email protected]>
1 parent 2bd34d6 commit 80d1f07

5 files changed

Lines changed: 128 additions & 14 deletions

File tree

example/index.php

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,13 @@
2727

2828
$param = JSignParam::instance();
2929

30-
$param->setJavaVersion('openjdk version "21.0.7" 2025-04-15 LTS');
30+
$param->setJavaVersion('openjdk version "21.0.8" 2025-07-15 LTS');
3131
$param->setJavaDownloadUrl('https://github.com/adoptium/temurin21-binaries/releases/download/jdk-21.0.8%2B9/OpenJDK21U-jre_x64_linux_hotspot_21.0.8_9.tar.gz');
32-
$param->setJavaPath(__DIR__ . '/../tmp/java');
32+
$param->setJavaPath(__DIR__ . '/../tmp/java/bin/java');
33+
34+
$param->setJsignPdfVersion('asdfasd');
35+
$param->setJSignPdfDownloadUrl('https://github.com/intoolswetrust/jsignpdf/releases/download/JSignPdf_2_3_0/jsignpdf-2.3.0.zip');
36+
$param->setjSignPdfJarPath(__DIR__ . '/../tmp/jsignpdf/JSignPdf.jar');
3337

3438
$param->setCertificate($pfxCertificateContent);
3539
$param->setPdf(file_get_contents(__DIR__ . '/../tests/resources/pdf-test.pdf'));
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Jeidison\JSignPDF\Runtime;
6+
7+
use InvalidArgumentException;
8+
use Jeidison\JSignPDF\Sign\JSignParam;
9+
use PharData;
10+
use PharException;
11+
use RuntimeException;
12+
use UnexpectedValueException;
13+
use ZipArchive;
14+
15+
class JSignPdfRuntimeService
16+
{
17+
public function getPath(JSignParam $params): string
18+
{
19+
$jsignPdfPath = $params->getjSignPdfJarPath();
20+
$downloadUrl = $params->getJSignPdfDownloadUrl();
21+
22+
if ($jsignPdfPath && !$downloadUrl) {
23+
if (file_exists($jsignPdfPath)) {
24+
return $jsignPdfPath;
25+
}
26+
throw new InvalidArgumentException('Jar of JSignPDF not found on path: '. $jsignPdfPath);
27+
}
28+
29+
if ($downloadUrl && $jsignPdfPath) {
30+
$baseDir = preg_replace('/\/JSignPdf.jar$/', '', $jsignPdfPath);
31+
if (!is_dir($baseDir)) {
32+
throw new InvalidArgumentException('The JSignPdf base dir is not a real directory: '. $baseDir);
33+
}
34+
self::downloadAndExtract($params);
35+
return $jsignPdfPath;
36+
}
37+
38+
throw new InvalidArgumentException('Java not found.');
39+
}
40+
41+
private function downloadAndExtract(JSignParam $params): void
42+
{
43+
$jsignPdfPath = $params->getjSignPdfJarPath();
44+
$url = $params->getJSignPdfDownloadUrl();
45+
46+
$baseDir = preg_replace('/\/JSignPdf.jar$/', '', $jsignPdfPath);
47+
48+
if (!is_dir($baseDir)) {
49+
$ok = mkdir($baseDir, 0755, true);
50+
if (!$ok) {
51+
throw new RuntimeException('Failure to create the folder: ' . $baseDir);
52+
}
53+
}
54+
if (!filter_var($url, FILTER_VALIDATE_URL)) {
55+
throw new InvalidArgumentException('The url to download Java is invalid: ' . $url);
56+
}
57+
$this->chunkDownload($url, $baseDir . '/jsignpdf.zip');
58+
$z = new ZipArchive();
59+
$ok = $z->open($baseDir . '/jsignpdf.zip');
60+
if ($ok !== true) {
61+
throw new InvalidArgumentException('The file ' . $baseDir . '/jsignpdf.zip cannot be extracted');
62+
}
63+
$ok = $z->extractTo(pathto: $baseDir, files: [$z->getNameIndex(0) . 'JSignPdf.jar']);
64+
if ($ok !== true) {
65+
throw new InvalidArgumentException('JSignPdf.jar not found inside path: ' . $z->getNameIndex(0) . 'JSignPdf.jar');
66+
}
67+
@exec('mv ' . escapeshellarg($baseDir . '/'. $z->getNameIndex(0)) . '/JSignPdf.jar ' . escapeshellarg($baseDir));
68+
@exec('rm -rf ' . escapeshellarg($baseDir . '/'. $z->getNameIndex(0)));
69+
unlink($baseDir . '/jsignpdf.zip');
70+
if (!file_exists($baseDir . '/JSignPdf.jar')) {
71+
throw new RuntimeException('Java binary not found at: ' . $baseDir . '/bin/java');
72+
}
73+
}
74+
75+
private function chunkDownload(string $url, string $destination): void
76+
{
77+
$fp = fopen($destination, 'w');
78+
79+
if ($fp) {
80+
$ch = curl_init($url);
81+
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
82+
curl_setopt($ch, CURLOPT_FILE, $fp);
83+
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
84+
$response = curl_exec($ch);
85+
if ($response === false) {
86+
throw new InvalidArgumentException('Failure to download file using the url ' . $url);
87+
}
88+
curl_close($ch);
89+
fclose($fp);
90+
} else {
91+
throw new InvalidArgumentException("Failute to download file using the url $url");
92+
}
93+
}
94+
}

src/Runtime/JavaRuntimeService.php

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,17 @@ public function getPath(JSignParam $params): string
3030
}
3131

3232
if ($downloadUrl && $javaPath) {
33-
$baseDir = rtrim($javaPath, '/bin/java');
33+
$baseDir = preg_replace('/\/bin\/java$/', '', $javaPath);
3434
if (!is_dir($baseDir)) {
35-
throw new InvalidArgumentException('The java base dir is not a real directory: '. $baseDir);
35+
throw new InvalidArgumentException('The java base dir is not a real directory. Create this directory first: '. $baseDir);
3636
}
3737
try {
3838
self::validateVersion($params);
3939
} catch (RuntimeException) {
4040
self::downloadAndExtract($downloadUrl, $javaPath);
4141
}
42+
$params->setJavaDownloadUrl('');
43+
$params->setJavaPath($javaPath);
4244
return $javaPath;
4345
}
4446

@@ -53,7 +55,7 @@ private function validateVersion(JSignParam $params): bool
5355
}
5456
$javaPath = $params->getJavaPath();
5557
\exec($javaPath . ' -version 2>&1', $javaVersion, $resultCode);
56-
if (empty($javaVersion)) {
58+
if (count($javaVersion) <= 1) {
5759
throw new RuntimeException('Failed to execute Java. Sounds that your operational system is blocking the JVM.');
5860
}
5961
if ($resultCode !== 0) {
@@ -65,7 +67,7 @@ private function validateVersion(JSignParam $params): bool
6567

6668
private function downloadAndExtract(string $url, string $baseDir): void
6769
{
68-
$baseDir = rtrim($baseDir, '/bin/java');
70+
$baseDir = preg_replace('/\/bin\/java$/', '', $baseDir);
6971

7072
if (!is_dir($baseDir)) {
7173
$ok = mkdir($baseDir, 0755, true);
@@ -98,6 +100,7 @@ private function downloadAndExtract(string $url, string $baseDir): void
98100

99101
private function findRootDir(PharData $phar, $rootDir) {
100102
$files = new \RecursiveIteratorIterator($phar, \RecursiveIteratorIterator::CHILD_FIRST);
103+
$rootDir = realpath($rootDir);
101104

102105
foreach ($files as $file) {
103106
$pathName = $file->getPathname();

src/Sign/JSignParam.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ class JSignParam
2121
private ?string $javaVersion = null;
2222
private ?string $javaDownloadUrl = null;
2323
private ?string $jSignPdfDownloadUrl = null;
24+
private ?string $jsignPdfVersion = null;
2425

2526
public function __construct()
2627
{
@@ -135,6 +136,17 @@ public function getjSignPdfJarPath()
135136
return $this->jSignPdfJarPath;
136137
}
137138

139+
public function setJsignPdfVersion(string $version): self
140+
{
141+
$this->jsignPdfVersion = $version;
142+
return $this;
143+
}
144+
145+
public function getJsignPdfVersion(): ?string
146+
{
147+
return $this->jsignPdfVersion;
148+
}
149+
138150
public function isOutputTypeBase64(): bool
139151
{
140152
return $this->isOutputTypeBase64;

src/Sign/JSignService.php

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use Exception;
66
use Jeidison\JSignPDF\JSignFileService;
77
use Jeidison\JSignPDF\Runtime\JavaRuntimeService;
8+
use Jeidison\JSignPDF\Runtime\JSignPdfRuntimeService;
89
use Throwable;
910

1011
/**
@@ -70,11 +71,8 @@ private function repackCertificateIfPasswordIsUnicode(JSignParam $params, $cert,
7071
public function getVersion(JSignParam $params)
7172
{
7273
$java = $this->javaCommand($params);
74+
$jSignPdf = $this->getjSignPdfJarPath($params);
7375
$jSignPdf = $params->getjSignPdfJarPath();
74-
if (!$jSignPdf && class_exists('JSignPDF\JSignPDFBin\JSignPdfPathService')) {
75-
$jSignPdf = \JSignPDF\JSignPDFBin\JSignPdfPathService::jSignPdfJarPath();
76-
}
77-
$this->throwIf(!file_exists($jSignPdf), 'Jar of JSignPDF not found on path: '. $jSignPdf);
7876

7977
$command = "$java -jar $jSignPdf --version 2>&1";
8078
\exec($command, $output);
@@ -121,10 +119,7 @@ private function commandSign(JSignParam $params)
121119
{
122120
list ($pdf, $certificate) = $this->storeTempFiles($params);
123121
$java = $this->javaCommand($params);
124-
$jSignPdf = $params->getjSignPdfJarPath();
125-
if (!$jSignPdf && class_exists('JSignPDF\JSignPDFBin\JSignPdfPathService')) {
126-
$jSignPdf = \JSignPDF\JSignPDFBin\JSignPdfPathService::jSignPdfJarPath();
127-
}
122+
$jSignPdf = $this->getjSignPdfJarPath($params);
128123
$this->throwIf(!file_exists($jSignPdf), 'Jar of JSignPDF not found on path: '. $jSignPdf);
129124

130125
$password = escapeshellarg($params->getPassword());
@@ -137,6 +132,12 @@ private function javaCommand(JSignParam $params): string
137132
return $javaRuntimeService->getPath($params);
138133
}
139134

135+
private function getjSignPdfJarPath(JSignParam $params): string
136+
{
137+
$JsignPdfRuntimeService = new JSignPdfRuntimeService();
138+
return $JsignPdfRuntimeService->getPath($params);
139+
}
140+
140141
private function throwIf($condition, $message)
141142
{
142143
if ($condition)

0 commit comments

Comments
 (0)