Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
56 / 56
100.00% covered (success)
100.00%
4 / 4
CRAP
100.00% covered (success)
100.00%
1 / 1
PDFtkSetupCheck
100.00% covered (success)
100.00%
56 / 56
100.00% covered (success)
100.00%
4 / 4
13
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
1
 getName
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getCategory
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 run
100.00% covered (success)
100.00%
46 / 46
100.00% covered (success)
100.00%
1 / 1
10
1<?php
2
3declare(strict_types=1);
4/**
5 * SPDX-FileCopyrightText: 2026 LibreCode coop and contributors
6 * SPDX-License-Identifier: AGPL-3.0-or-later
7 */
8
9namespace OCA\Libresign\SetupCheck;
10
11use OCA\Libresign\AppInfo\Application;
12use OCA\Libresign\Helper\JavaHelper;
13use OCA\Libresign\Service\Install\InstallService;
14use OCA\Libresign\Service\Install\SignSetupService;
15use OCP\App\IAppManager;
16use OCP\IAppConfig;
17use OCP\IConfig;
18use OCP\IL10N;
19use OCP\IURLGenerator;
20use OCP\SetupCheck\ISetupCheck;
21use OCP\SetupCheck\SetupResult;
22use Psr\Log\LoggerInterface;
23
24class PDFtkSetupCheck implements ISetupCheck {
25    use SetupCheckUtils;
26
27    private IL10N $l10n;
28    private IAppConfig $appConfig;
29    private IConfig $systemConfig;
30    private JavaHelper $javaHelper;
31
32    private SignSetupService $signSetupService;
33    private IURLGenerator $urlGenerator;
34    private IAppManager $appManager;
35    private LoggerInterface $logger;
36
37    public function __construct(
38        IL10N $l10n,
39        IAppConfig $appConfig,
40        SignSetupService $signSetupService,
41        IURLGenerator $urlGenerator,
42        IAppManager $appManager,
43        LoggerInterface $logger,
44        IConfig $systemConfig,
45        JavaHelper $javaHelper,
46    ) {
47        $this->l10n = $l10n;
48        $this->appConfig = $appConfig;
49        $this->signSetupService = $signSetupService;
50        $this->urlGenerator = $urlGenerator;
51        $this->appManager = $appManager;
52        $this->logger = $logger;
53        $this->systemConfig = $systemConfig;
54        $this->javaHelper = $javaHelper;
55    }
56
57    #[\Override]
58    public function getName(): string {
59        return 'PDFtk';
60    }
61
62    #[\Override]
63    public function getCategory(): string {
64        return 'system';
65    }
66
67    #[\Override]
68    public function run(): SetupResult {
69        $debugEnabled = $this->systemConfig->getSystemValueBool('debug', false);
70        $pdftkPath = $this->appConfig->getValueString(Application::APP_ID, 'pdftk_path');
71
72        if (!$pdftkPath) {
73            return SetupResult::error(
74                // TRANSLATORS Nextcloud administration overview warning. PDFtk is the Java tool LibreSign uses to stamp the signature footer onto PDFs; the configured path is empty.
75                $this->l10n->t('PDFtk not found'),
76                // TRANSLATORS Tip under a Nextcloud administration overview error. Instructs the server administrator to install PDFtk for LibreSign via the Nextcloud occ CLI.
77                $this->l10n->t('Run occ libresign:install --pdftk')
78            );
79        }
80
81        $verifyResult = $this->verifyResourceIntegrity('pdftk', $debugEnabled);
82        if (!empty($verifyResult)) {
83            [$errorMsg, $tip] = $this->getErrorAndTipFromVerify($verifyResult, 'pdftk', $debugEnabled, $this->l10n);
84            return SetupResult::error($errorMsg, $tip);
85        }
86
87        if (!file_exists($pdftkPath)) {
88            return SetupResult::error(
89                // TRANSLATORS Nextcloud administration overview warning. PDFtk stamps LibreSign's PDF footer during signing; %s is the configured filesystem path that does not exist.
90                $this->l10n->t('PDFtk binary not found: %s', [$pdftkPath]),
91                // TRANSLATORS Tip under a Nextcloud administration overview error. Instructs the server administrator to install PDFtk for LibreSign via the Nextcloud occ CLI.
92                $this->l10n->t('Run occ libresign:install --pdftk')
93            );
94        }
95
96        $javaPath = $this->javaHelper->getJavaPath();
97        if (!$javaPath || !file_exists($javaPath)) {
98            return SetupResult::error(
99                // TRANSLATORS Nextcloud administration overview warning. LibreSign runs PDFtk as a Java JAR to write the signed PDF footer, so a working Java runtime is required.
100                $this->l10n->t('Necessary Java to run PDFtk'),
101                // TRANSLATORS Tip under a Nextcloud administration overview error. Instructs the server administrator to install the Java runtime LibreSign needs via the Nextcloud occ CLI.
102                $this->l10n->t('Run occ libresign:install --java')
103            );
104        }
105
106        /** @var list<string> $versionOutput */
107        exec($javaPath . ' -jar ' . $pdftkPath . ' --version 2>&1', $versionOutput, $resultCode);
108        if (empty($versionOutput) || $resultCode !== 0) {
109            return SetupResult::error(
110                // TRANSLATORS Nextcloud administration overview warning. LibreSign could not read the PDFtk version string used to stamp signed PDF footers.
111                $this->l10n->t('Failure to check PDFtk version.'),
112                // TRANSLATORS Tip under a Nextcloud administration overview error. Instructs the server administrator to reinstall PDFtk for LibreSign via the Nextcloud occ CLI.
113                $this->l10n->t('Run occ libresign:install --pdftk')
114            );
115        }
116
117        $versionLine = $versionOutput[0] ?? '';
118        preg_match('/pdftk port to java (?<version>.*) a Handy Tool/', $versionLine, $matches);
119        $version = $matches['version'] ?? null;
120
121        if (!$version) {
122            return SetupResult::error(
123                // TRANSLATORS Nextcloud administration overview warning. The file at %s does not look like the PDFtk JAR LibreSign expects for PDF footer stamping.
124                $this->l10n->t('PDFtk binary is invalid: %s', [$pdftkPath]),
125                // TRANSLATORS Tip under a Nextcloud administration overview error. Instructs the server administrator to reinstall PDFtk for LibreSign via the Nextcloud occ CLI.
126                $this->l10n->t('Run occ libresign:install --pdftk')
127            );
128        }
129
130        if ($version !== InstallService::PDFTK_VERSION) {
131            return SetupResult::error(
132                $this->l10n->t('Necessary install the version %s', [InstallService::PDFTK_VERSION]),
133                $this->l10n->t('Run occ libresign:install --pdftk')
134            );
135        }
136
137        $messages = [
138            // TRANSLATORS Success detail in Nextcloud administration overview showing the detected PDFtk version. %s is the version string.
139            $this->l10n->t('PDFtk version: %s', [$version]),
140            // TRANSLATORS Success detail in Nextcloud administration overview showing the PDFtk path. %s is the filesystem path.
141            $this->l10n->t('PDFtk path: %s', [$pdftkPath]),
142        ];
143        return SetupResult::success(implode("\n", $messages));
144    }
145}