diff --git a/lib/Migration/Version2040Date20211027183759.php b/lib/Migration/Version2040Date20211027183759.php
index 8d83d48609..d5ad0911b0 100644
--- a/lib/Migration/Version2040Date20211027183759.php
+++ b/lib/Migration/Version2040Date20211027183759.php
@@ -6,13 +6,10 @@
use Closure;
use Doctrine\DBAL\Types\Types;
-use OC\SystemConfig;
-use OCA\Libresign\AppInfo\Application;
-use OCA\Libresign\Command\Install;
+use OCA\Libresign\Service\PdfParserService;
use OCP\DB\ISchemaWrapper;
use OCP\Files\File;
use OCP\Files\IRootFolder;
-use OCP\IConfig;
use OCP\IDBConnection;
use OCP\Migration\IOutput;
use OCP\Migration\SimpleMigrationStep;
@@ -22,28 +19,20 @@
class Version2040Date20211027183759 extends SimpleMigrationStep {
/** @var IRootFolder*/
private $root;
- /** @var IDBConnection */
- private $connection;
- /** @var Install */
- private $install;
- /** @var IConfig */
- private $config;
- /** @var SystemConfig */
- private $systemConfig;
+ /** @var PdfParserService */
+ private $PdfParserService;
/** @var array */
private $rows;
- public function __construct(IRootFolder $root,
- IDBConnection $connection,
- IRootFolder $rootfolder,
- Install $install,
- IConfig $config,
- SystemConfig $systemConfig) {
+ public function __construct(IDBConnection $connection,
+ IRootFolder $root,
+ PdfParserService $PdfParserService) {
$this->connection = $connection;
$this->install = $install;
$this->config = $config;
$this->systemConfig = $systemConfig;
$this->rootFolder = $rootfolder;
$this->root = $root;
+ $this->PdfParserService = $PdfParserService;
}
public function preSchemaChange(IOutput $output, \Closure $schemaClosure, array $options): void {
@@ -81,7 +70,7 @@ public function postSchemaChange(IOutput $output, \Closure $schemaClosure, array
/** @var File[] */
$file = $userFolder->getById($row['node_id']);
if (count($file) >= 1) {
- $data = $this->getMetadataFromCli($cli, $file[0]->getPath());
+ $data = $this->PdfParserService->getMetadata($file[0]->getPath());
$json = json_encode($data);
$query = $this->connection->getQueryBuilder();
$query
@@ -89,7 +78,7 @@ public function postSchemaChange(IOutput $output, \Closure $schemaClosure, array
->set('metadata', $query->createNamedParameter($json))
->where($query->expr()->eq('id', $query->createNamedParameter($row['id'])));
- $query->execute();
+ $query->executeStatement();
}
}
}
diff --git a/lib/Service/InstallService.php b/lib/Service/InstallService.php
new file mode 100644
index 0000000000..78dde44dda
--- /dev/null
+++ b/lib/Service/InstallService.php
@@ -0,0 +1,337 @@
+tempManager = $tempManager;
+ $this->clientService = $clientService;
+ $this->config = $config;
+ $this->systemConfig = $systemConfig;
+ $this->rootFolder = $rootFolder;
+ }
+
+ public function setOutput(OutputInterface $output): void {
+ $this->output = $output;
+ }
+
+ public function getFolder($path = ''): Folder {
+ $rootFolder = $this->getAppRootFolder();
+ try {
+ $folder = $rootFolder->newFolder(Application::APP_ID . DIRECTORY_SEPARATOR . $path);
+ } catch (\Throwable $th) {
+ $folder = $rootFolder->get(Application::APP_ID . DIRECTORY_SEPARATOR . $path);
+ }
+ return $folder;
+ }
+
+ private function getAppDataFolderName(): string {
+ $instanceId = $this->systemConfig->getValue('instanceid', null);
+ if ($instanceId === null) {
+ throw new \RuntimeException('no instance id!');
+ }
+
+ return 'appdata_' . $instanceId;
+ }
+
+ private function getDataDir(): string {
+ $dataDir = $this->systemConfig->getValue('datadirectory', \OC::$SERVERROOT . '/data/');
+ return $dataDir;
+ }
+
+ private function getAppRootFolder(): Folder {
+ $path = $this->getAppDataFolderName();
+ try {
+ $folder = $this->rootFolder->get($path);
+ } catch (\Throwable $th) {
+ $folder = $this->rootFolder->newFolder($path);
+ }
+ return $folder;
+ }
+
+ public function getFullPath(): string {
+ $folder = $this->getFolder();
+ return $this->getDataDir() . '/' . $folder->getInternalPath();
+ }
+
+ public function installJava(): void {
+ $extractDir = $this->getFullPath();
+
+ /**
+ * To update:
+ * Check the compatible version of Java to use JSignPdf and update all the follow data
+ * URL used to get the MD5 and URL to download:
+ * https://jdk.java.net/java-se-ri/8-MR3
+ */
+ if (PHP_OS_FAMILY === 'Windows') {
+ $url = 'https://download.java.net/openjdk/jdk8u41/ri/openjdk-8u41-b04-windows-i586-14_jan_2020.zip';
+ $tempFile = $this->tempManager->getTemporaryFile('.zip');
+ $executableExtension = '.exe';
+ $class = ZIP::class;
+ $md5 = '48ac2152d1fb0ad1d343104be210d532';
+ } else {
+ $url = 'https://download.java.net/openjdk/jdk8u41/ri/openjdk-8u41-b04-linux-x64-14_jan_2020.tar.gz';
+ $tempFile = $this->tempManager->getTemporaryFile('.tar.gz');
+ $executableExtension = '';
+ $class = TAR::class;
+ $md5 = '35f515e9436f4fefad091db2c1450c5f';
+ }
+
+ $this->download($url, 'java', $tempFile, $md5);
+
+ $extractor = new $class($tempFile);
+ $extractor->extract($extractDir);
+
+ $this->config->setAppValue(Application::APP_ID, 'java_path', $extractDir . '/java-se-8u41-ri/bin/java' . $executableExtension);
+ }
+
+ public function uninstallJava(): void {
+ $javaPath = $this->config->getAppValue(Application::APP_ID, 'java_path');
+ if (!$javaPath) {
+ return;
+ }
+ $appFolder = $this->getAppRootFolder();
+ $name = $appFolder->getName();
+ // Remove prefix
+ $path = explode($name, $javaPath)[1];
+ // Remove binary path
+ $path = explode(DIRECTORY_SEPARATOR . 'bin' . DIRECTORY_SEPARATOR, $path)[0];
+ try {
+ $folder = $appFolder->get($path);
+ $folder->delete();
+ } catch (NotFoundException $e) {
+ }
+ $this->config->deleteAppValue(Application::APP_ID, 'java_path');
+ }
+
+ public function installJSignPdf(): void {
+ if (!extension_loaded('zip')) {
+ throw new RuntimeException('Zip extension is not available');
+ }
+ $extractDir = $this->getFullPath();
+
+ $tempFile = $this->tempManager->getTemporaryFile('.zip');
+ $url = 'https://sourceforge.net/projects/jsignpdf/files/stable/JSignPdf%20' . JSignPdfHandler::VERSION . '/jsignpdf-' . JSignPdfHandler::VERSION . '.zip';
+
+ $this->download($url, 'JSignPdf', $tempFile);
+
+ $zip = new ZIP($tempFile);
+ $zip->extract($extractDir);
+
+ $fullPath = $extractDir . DIRECTORY_SEPARATOR. 'jsignpdf-' . JSignPdfHandler::VERSION . DIRECTORY_SEPARATOR. 'JSignPdf.jar';
+ $this->config->setAppValue(Application::APP_ID, 'jsignpdf_jar_path', $fullPath);
+ }
+
+ public function uninstallJSignPdf(): void {
+ $jsignpdJarPath = $this->config->getAppValue(Application::APP_ID, 'jsignpdf_jar_path');
+ if (!$jsignpdJarPath) {
+ return;
+ }
+ $appFolder = $this->getAppRootFolder();
+ $name = $appFolder->getName();
+ // Remove prefix
+ $path = explode($name, $jsignpdJarPath)[1];
+ // Remove sufix
+ $path = trim($path, DIRECTORY_SEPARATOR . 'JSignPdf.jar');
+ try {
+ $folder = $appFolder->get($path);
+ $folder->delete();
+ } catch (NotFoundException $e) {
+ }
+ $this->config->deleteAppValue(Application::APP_ID, 'jsignpdf_jar_path');
+ }
+
+ public function installCli(): void {
+ $folder = $this->getFolder();
+
+ if (PHP_OS_FAMILY === 'Windows') {
+ throw new \RuntimeException('LibreSign CLI do not work in Windows!');
+ } elseif (PHP_OS_FAMILY === 'Darwin') {
+ $url = 'https://github.com/LibreSign/libresign-cli/releases/download/v0.0.4/libresign_0.0.4_Linux_arm64';
+ } elseif (PHP_OS_FAMILY === 'Linux') {
+ if (PHP_INT_SIZE === 4) {
+ $url = 'https://github.com/LibreSign/libresign-cli/releases/download/v0.0.4/libresign_0.0.4_Linux_i386';
+ } else {
+ $url = 'https://github.com/LibreSign/libresign-cli/releases/download/v0.0.4/libresign_0.0.4_Linux_x86_64';
+ }
+ }
+ $file = $folder->newFile('libresign-cli');
+ $fullPath = $this->getDataDir() . DIRECTORY_SEPARATOR . $file->getInternalPath();
+
+ $this->download($url, 'libresign-cli', $fullPath);
+
+ if (PHP_OS_FAMILY !== 'Windows') {
+ chmod($fullPath, 0700);
+ }
+
+ $this->config->setAppValue(Application::APP_ID, 'libresign_cli_path', $fullPath);
+ }
+
+ public function uninstallCli(): void {
+ $libresignCliPath = $this->config->getAppValue(Application::APP_ID, 'libresign_cli_path');
+ if (!$libresignCliPath) {
+ return;
+ }
+ $appFolder = $this->getAppRootFolder();
+ $name = $appFolder->getName();
+ // Remove prefix
+ $path = explode($name, $libresignCliPath)[1];
+ try {
+ $folder = $appFolder->get($path);
+ $folder->delete();
+ } catch (NotFoundException $e) {
+ }
+ $this->config->deleteAppValue(Application::APP_ID, 'libresign_cli_path');
+ }
+
+ public function installCfssl(): void {
+ $folder = $this->getFolder();
+
+ if (PHP_OS_FAMILY === 'Windows') {
+ $downloads = [
+ [
+ 'url' => 'https://github.com/cloudflare/cfssl/releases/download/v1.6.1/cfssl_1.6.1_windows_amd64.exe',
+ 'destination' => 'cfssl.exe',
+ ],
+ [
+ 'url' => 'https://github.com/cloudflare/cfssl/releases/download/v1.6.1/cfssljson_1.6.1_windows_amd64.exe',
+ 'destination' => 'cfssljson.exe',
+ ],
+ ];
+ } elseif (PHP_OS_FAMILY === 'Darwin') {
+ $downloads = [
+ [
+ 'url' => 'https://github.com/cloudflare/cfssl/releases/download/v1.6.1/cfssl_1.6.1_darwin_amd64',
+ 'destination' => 'cfssl',
+ ],
+ [
+ 'url' => 'https://github.com/cloudflare/cfssl/releases/download/v1.6.1/cfssljson_1.6.1_darwin_amd64',
+ 'destination' => 'cfssljson',
+ ],
+ ];
+ } else {
+ $downloads = [
+ [
+ 'url' => 'https://github.com/cloudflare/cfssl/releases/download/v1.6.1/cfssl_1.6.1_linux_amd64',
+ 'destination' => 'cfssl',
+ ],
+ [
+ 'url' => 'https://github.com/cloudflare/cfssl/releases/download/v1.6.1/cfssljson_1.6.1_linux_amd64',
+ 'destination' => 'cfssljson',
+ ],
+ ];
+ }
+ foreach ($downloads as $download) {
+ $file = $folder->newFile($download['destination']);
+ $fullPath = $this->getDataDir() . DIRECTORY_SEPARATOR . $file->getInternalPath();
+
+ $this->download($download['url'], $download['destination'], $fullPath);
+
+ if (PHP_OS_FAMILY !== 'Windows') {
+ chmod($fullPath, 0700);
+ }
+ }
+
+ $this->config->setAppValue(Application::APP_ID, 'cfssl_bin', 1);
+ }
+
+ public function uninstallCfssl(): void {
+ $cfsslPath = $this->config->getAppValue(Application::APP_ID, 'cfssl_bin');
+ if (!$cfsslPath) {
+ return;
+ }
+ $appFolder = $this->getAppRootFolder();
+ $name = $appFolder->getName();
+ // Remove prefix
+ $path = explode($name, $cfsslPath)[1];
+ try {
+ $folder = $appFolder->get($path);
+ $folder->delete();
+ } catch (NotFoundException $e) {
+ }
+ $this->config->deleteAppValue(Application::APP_ID, 'cfssl_bin');
+ }
+
+ protected function download(string $url, string $filename, string $path, ?string $md5 = '') {
+ if (php_sapi_name() === 'cli' && $this->output instanceof OutputInterface) {
+ $this->downloadCli($url, $filename, $path, $md5);
+ return;
+ }
+ $client = $this->clientService->newClient();
+ try {
+ $client->get($url, [
+ 'sink' => $path,
+ 'timeout' => 0
+ ]);
+ } catch (\Exception $e) {
+ throw new LibresignException('Failure on download ' . $filename . " try again.\n" . $e->getMessage());
+ }
+ if ($md5 && file_exists($path) && md5_file($path) !== $md5) {
+ throw new LibresignException('Failure on download ' . $filename . ' try again. Invalid md5.');
+ }
+ }
+
+ protected function downloadCli(string $url, string $filename, string $path, ?string $md5 = '') {
+ $client = $this->clientService->newClient();
+ $progressBar = new ProgressBar($this->output);
+ $this->output->writeln('Downloading ' . $filename . '...');
+ $progressBar->start();
+ try {
+ $client->get($url, [
+ 'sink' => $path,
+ 'timeout' => 0,
+ 'progress' => function ($downloadSize, $downloaded) use ($progressBar) {
+ $progressBar->setMaxSteps($downloadSize);
+ $progressBar->setProgress($downloaded);
+ },
+ ]);
+ } catch (\Exception $e) {
+ $this->output->writeln('Failure on download ' . $filename . ' try again.');
+ $this->output->writeln('' . $e->getMessage() . '');
+ }
+ $progressBar->finish();
+ $this->output->writeln('');
+ $progressBar->finish();
+ if ($md5 && file_exists($path) && md5_file($path) !== $md5) {
+ $this->output->writeln('Failure on download ' . $filename . ' try again');
+ $this->output->writeln('Invalid MD5');
+ }
+ }
+}
diff --git a/lib/Service/PdfParserService.php b/lib/Service/PdfParserService.php
new file mode 100644
index 0000000000..1eaa389ce3
--- /dev/null
+++ b/lib/Service/PdfParserService.php
@@ -0,0 +1,58 @@
+systemConfig = $systemConfig;
+ $this->config = $config;
+ $this->installService = $installService;
+ $this->cliPath = $this->getLibesignCli();
+ }
+
+ private function getDataDir(): string {
+ return $this->systemConfig->getValue('datadirectory', \OC::$SERVERROOT . '/data/');
+ }
+
+ public function getMetadata(string $filePath): array {
+ $fullPath = $this->getDataDir() . $filePath;
+ $json = shell_exec($this->cliPath . ' info ' . $fullPath);
+ $array = json_decode($json, true);
+ $output = [
+ 'p' => count($array['pages']),
+ ];
+ foreach ($array['pages'] as $page) {
+ $output['d'][] = [
+ 'w' => $page['width'],
+ 'h' => $page['height'],
+ ];
+ }
+ return $output;
+ }
+
+ private function getLibesignCli(): string {
+ $path = $this->config->getAppValue(Application::APP_ID, 'libresign_cli_path');
+ if (!file_exists($path)) {
+ $this->installService->installCli();
+ $path = $this->config->getAppValue(Application::APP_ID, 'libresign_cli_path');
+ }
+ return $path;
+ }
+}
diff --git a/lib/Service/SignFileService.php b/lib/Service/SignFileService.php
index d17da02f6d..6cf95efa52 100644
--- a/lib/Service/SignFileService.php
+++ b/lib/Service/SignFileService.php
@@ -15,7 +15,6 @@
use OCA\Libresign\Exception\LibresignException;
use OCA\Libresign\Handler\Pkcs7Handler;
use OCA\Libresign\Handler\Pkcs12Handler;
-use OCA\Libresign\Handler\TCPDILibresign;
use OCA\Libresign\Helper\JSActions;
use OCA\Libresign\Helper\ValidateHelper;
use OCP\Accounts\IAccountManager;
@@ -91,6 +90,10 @@ class SignFileService {
private $eventDispatcher;
/** @var IURLGenerator */
private $urlGenerator;
+ /** @var IMimeTypeDetector */
+ private $mimeTypeDetector;
+ /** @var PdfParserService */
+ private $pdfParserService;
/** @var ITempManager */
private $tempManager;
/** @var FileUserEntity */
@@ -129,6 +132,7 @@ public function __construct(
FileElementService $fileElementService,
IEventDispatcher $eventDispatcher,
IURLGenerator $urlGenerator,
+ PdfParserService $pdfParserService,
IMimeTypeDetector $mimeTypeDetector,
ITempManager $tempManager
) {
@@ -156,6 +160,7 @@ public function __construct(
$this->fileElementService = $fileElementService;
$this->eventDispatcher = $eventDispatcher;
$this->urlGenerator = $urlGenerator;
+ $this->pdfParserService = $pdfParserService;
$this->mimeTypeDetector = $mimeTypeDetector;
$this->tempManager = $tempManager;
}
@@ -232,9 +237,7 @@ public function getFileMetadata(\OCP\Files\Node $node): array {
'extension' => $node->getExtension(),
];
if ($metadata['extension'] === 'pdf') {
- $pdf = new TCPDILibresign();
- $pdf->setSourceData($node->getContent());
- $metadata = array_merge($metadata, $pdf->getPagesMetadata());
+ $metadata = $this->pdfParserService->getMetadata($node->getPath());
}
return $metadata;
}
diff --git a/tests/Unit/Service/SignFileServiceTest.php b/tests/Unit/Service/SignFileServiceTest.php
index 0764f21288..1e067aefee 100644
--- a/tests/Unit/Service/SignFileServiceTest.php
+++ b/tests/Unit/Service/SignFileServiceTest.php
@@ -14,6 +14,7 @@
use OCA\Libresign\Service\FileElementService;
use OCA\Libresign\Service\FolderService;
use OCA\Libresign\Service\MailService;
+use OCA\Libresign\Service\PdfParserService;
use OCA\Libresign\Service\SignFileService;
use OCP\Accounts\IAccountManager;
use OCP\App\IAppManager;
@@ -84,6 +85,8 @@ final class SignFileServiceTest extends \OCA\Libresign\Tests\Unit\TestCase {
private $eventDispatcher;
/** @var IURLGenerator|MockObject */
private $urlGenerator;
+ /** @var PdfParserService */
+ private $pdfParserService;
/** @var IMimeTypeDetector|MockObject */
private $mimeTypeDetector;
/** @var ITempManager|MockObject */
@@ -118,6 +121,7 @@ public function setUp(): void {
$this->fileElementService = $this->createMock(FileElementService::class);
$this->eventDispatcher = $this->createMock(IEventDispatcher::class);
$this->urlGenerator = $this->createMock(IURLGenerator::class);
+ $this->pdfParserService = $this->createMock(PdfParserService::class);
$this->mimeTypeDetector = $this->createMock(IMimeTypeDetector::class);
$this->tempManager = $this->createMock(ITempManager::class);
}
@@ -148,6 +152,7 @@ private function getService(): SignFileService {
$this->fileElementService,
$this->eventDispatcher,
$this->urlGenerator,
+ $this->pdfParserService,
$this->mimeTypeDetector,
$this->tempManager
);