mirror of
https://github.com/LibreSign/libresign.git
synced 2025-12-18 05:20:45 +01:00
feat: add PdfSignatureDetectionService for detecting existing signatures
This service provides a dedicated, testable way to detect if a PDF already contains signatures. It encapsulates the signature detection logic that was previously scattered across multiple handlers. The service creates a memory resource from PDF content and uses the SignEngineFactory to check for existing certificate chains. It handles exceptions gracefully and returns false for any detection failures. Tests use real PDF fixtures (signed and unsigned) instead of mocks, providing better confidence in the detection logic. Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
This commit is contained in:
parent
252018adb3
commit
cd7db4ea37
2 changed files with 101 additions and 0 deletions
48
lib/Service/PdfSignatureDetectionService.php
Normal file
48
lib/Service/PdfSignatureDetectionService.php
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2020-2024 LibreCode coop and contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
namespace OCA\Libresign\Service;
|
||||
|
||||
use OCA\Libresign\Handler\SignEngine\SignEngineFactory;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
class PdfSignatureDetectionService {
|
||||
public function __construct(
|
||||
private SignEngineFactory $signEngineFactory,
|
||||
private LoggerInterface $logger,
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a PDF has existing signatures
|
||||
*
|
||||
* @param string $pdfContent The PDF file content
|
||||
* @return bool True if the file has signatures, false otherwise
|
||||
*/
|
||||
public function hasSignatures(string $pdfContent): bool {
|
||||
$resource = fopen('php://memory', 'r+');
|
||||
if ($resource === false) {
|
||||
$this->logger->warning('Failed to create resource for signature detection');
|
||||
return false;
|
||||
}
|
||||
|
||||
fwrite($resource, $pdfContent);
|
||||
rewind($resource);
|
||||
|
||||
try {
|
||||
$engine = $this->signEngineFactory->resolve('pdf');
|
||||
$certificates = $engine->getCertificateChain($resource);
|
||||
return !empty($certificates);
|
||||
} catch (\Throwable $e) {
|
||||
$this->logger->debug('Failed to detect signatures: ' . $e->getMessage());
|
||||
return false;
|
||||
} finally {
|
||||
fclose($resource);
|
||||
}
|
||||
}
|
||||
}
|
||||
53
tests/php/Unit/Service/PdfSignatureDetectionServiceTest.php
Normal file
53
tests/php/Unit/Service/PdfSignatureDetectionServiceTest.php
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2020-2024 LibreCode coop and contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
namespace OCA\Libresign\Tests\Unit\Service;
|
||||
|
||||
use OCA\Libresign\Handler\SignEngine\SignEngineFactory;
|
||||
use OCA\Libresign\Service\PdfSignatureDetectionService;
|
||||
use OCA\Libresign\Tests\Unit\PdfFixtureTrait;
|
||||
use OCA\Libresign\Tests\Unit\TestCase;
|
||||
use PHPUnit\Framework\Attributes\DataProvider;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
class PdfSignatureDetectionServiceTest extends TestCase {
|
||||
use PdfFixtureTrait;
|
||||
|
||||
private PdfSignatureDetectionService $service;
|
||||
|
||||
public function setUp(): void {
|
||||
parent::setUp();
|
||||
|
||||
$signEngineFactory = \OCP\Server::get(SignEngineFactory::class);
|
||||
$logger = \OCP\Server::get(LoggerInterface::class);
|
||||
|
||||
$this->service = new PdfSignatureDetectionService(
|
||||
$signEngineFactory,
|
||||
$logger
|
||||
);
|
||||
}
|
||||
|
||||
public static function pdfContentProvider(): array {
|
||||
$fixture = new class { use PdfFixtureTrait; };
|
||||
|
||||
return [
|
||||
'signed PDF with DocMDP level 1' => [fn() => $fixture->createPdfWithDocMdp(1), true],
|
||||
'signed PDF with DocMDP level 2' => [fn() => $fixture->createPdfWithDocMdp(2), true],
|
||||
'signed PDF with DocMDP level 3' => [fn() => $fixture->createPdfWithDocMdp(3), true],
|
||||
'unsigned minimal PDF' => [fn() => $fixture->createMinimalPdf(), false],
|
||||
'empty string' => [fn() => '', false],
|
||||
'invalid content' => [fn() => 'not a valid pdf content', false],
|
||||
];
|
||||
}
|
||||
|
||||
#[DataProvider('pdfContentProvider')]
|
||||
public function testHasSignatures(callable $pdfProvider, bool $expected): void {
|
||||
$result = $this->service->hasSignatures($pdfProvider());
|
||||
$this->assertSame($expected, $result);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue