Skip to content

Commit ce38f29

Browse files
authored
Merge pull request #4546 from LibreSign/fix/prevent-generate-a-path-without-existing-folder
fix: prevent generate a path without existing folder
2 parents c499657 + b8c9883 commit ce38f29

2 files changed

Lines changed: 96 additions & 89 deletions

File tree

lib/Service/Install/InstallService.php

Lines changed: 78 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -117,17 +117,13 @@ private function getFolder(string $path = '', ?ISimpleFolder $folder = null, $ne
117117
throw new LibresignException(
118118
$e->getMessage() . '. ' .
119119
'Permission problems. ' .
120-
'Maybe this could fix: chown -R ' . $user['name'] . ' ' . $this->getDataDir()
120+
'Maybe this could fix: chown -R ' . $user['name'] . ' ' . $this->getInternalPathOfFolder($folder)
121121
);
122122
}
123123
}
124124
return $folder;
125125
}
126126

127-
private function getEmptyFolder(string $path): ISimpleFolder {
128-
return $this->getFolder($path, null, true);
129-
}
130-
131127
/**
132128
* @todo check a best solution to don't use reflection
133129
*/
@@ -137,7 +133,7 @@ private function getInternalPathOfFolder(ISimpleFolder $node): string {
137133
$reflectionProperty->setAccessible(true);
138134
$folder = $reflectionProperty->getValue($node);
139135
$path = $folder->getInternalPath();
140-
return $path;
136+
return $this->getDataDir() . '/' . $path;
141137
}
142138

143139
/**
@@ -156,19 +152,14 @@ private function getInternalPathOfFile(ISimpleFile $node): string {
156152
$file = $reflectionProperty->getValue($node);
157153
$path = $file->getPath();
158154
}
159-
return $path;
155+
return $this->getDataDir() . '/' . $path;
160156
}
161157

162158
private function getDataDir(): string {
163159
$dataDir = $this->config->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data/');
164160
return $dataDir;
165161
}
166162

167-
private function getFullPath(): string {
168-
$folder = $this->getFolder();
169-
return $this->getDataDir() . '/' . $this->getInternalPathOfFolder($folder);
170-
}
171-
172163
private function runAsync(): void {
173164
$resource = $this->resource;
174165
$process = new Process([OC::$SERVERROOT . '/occ', 'libresign:install', '--' . $resource]);
@@ -380,12 +371,16 @@ public function installJava(?bool $async = false): void {
380371
if (PHP_OS_FAMILY !== 'Linux') {
381372
throw new RuntimeException(sprintf('OS_FAMILY %s is incompatible with LibreSign.', PHP_OS_FAMILY));
382373
}
383-
$linuxDistribution = $this->getLinuxDistributionToDownloadJava();
384-
$extractDir = $this->getFullPath() . '/' . $linuxDistribution . '/' . $this->resource;
385374

386-
$downloadOk = $this->isDownloadedFilesOk();
387-
if (!$downloadOk) {
388-
$folder = $this->getEmptyFolder($this->resource);
375+
if ($this->isDownloadedFilesOk()) {
376+
// The binaries files could exists but not saved at database
377+
if (!$this->appConfig->getValueString(Application::APP_ID, 'java_path')) {
378+
$linuxDistribution = $this->getLinuxDistributionToDownloadJava();
379+
$folder = $this->getFolder('/' . $linuxDistribution . '/' . $this->resource);
380+
$extractDir = $this->getInternalPathOfFolder($folder);
381+
$this->appConfig->setValueString(Application::APP_ID, 'java_path', $extractDir . '/jdk-' . self::JAVA_URL_PATH_NAME . '-jre/bin/java');
382+
}
383+
} else {
389384
/**
390385
* Steps to update:
391386
* Check the compatible version of Java to use JSignPdf
@@ -394,6 +389,7 @@ public function installJava(?bool $async = false): void {
394389
* URL used to get the MD5 and URL to download:
395390
* https://jdk.java.net/java-se-ri/8-MR3
396391
*/
392+
$linuxDistribution = $this->getLinuxDistributionToDownloadJava();
397393
$slugfyVersionNumber = str_replace('+', '_', self::JAVA_URL_PATH_NAME);
398394
if ($this->architecture === 'x86_64') {
399395
$compressedFileName = 'OpenJDK21U-jre_x64_' . $linuxDistribution . '_hotspot_' . $slugfyVersionNumber . '.tar.gz';
@@ -402,26 +398,24 @@ public function installJava(?bool $async = false): void {
402398
$compressedFileName = 'OpenJDK21U-jre_aarch64_' . $linuxDistribution . '_hotspot_' . $slugfyVersionNumber . '.tar.gz';
403399
$url = 'https://github.com/adoptium/temurin21-binaries/releases/download/jdk-' . self::JAVA_URL_PATH_NAME . '/' . $compressedFileName;
404400
}
405-
$checksumUrl = $url . '.sha256.txt';
406-
$hash = $this->getHash($compressedFileName, $checksumUrl);
401+
$folder = $this->getFolder('/' . $linuxDistribution . '/' . $this->resource);
407402
try {
408403
$compressedFile = $folder->getFile($compressedFileName);
409404
} catch (NotFoundException $th) {
410405
$compressedFile = $folder->newFile($compressedFileName);
411406
}
412-
$comporessedInternalFileName = $this->getDataDir() . '/' . $this->getInternalPathOfFile($compressedFile);
413407

408+
$comporessedInternalFileName = $this->getInternalPathOfFile($compressedFile);
414409
$dependencyName = 'java ' . $this->architecture . ' ' . $linuxDistribution;
410+
$checksumUrl = $url . '.sha256.txt';
411+
$hash = $this->getHash($compressedFileName, $checksumUrl);
415412
$this->download($url, $dependencyName, $comporessedInternalFileName, $hash, 'sha256');
416413

417414
$extractor = new TAR($comporessedInternalFileName);
415+
$extractDir = $this->getInternalPathOfFolder($folder);
418416
$extractor->extract($extractDir);
419417
unlink($comporessedInternalFileName);
420-
$downloadOk = true;
421-
}
422-
423-
$this->appConfig->setValueString(Application::APP_ID, 'java_path', $extractDir . '/jdk-' . self::JAVA_URL_PATH_NAME . '-jre/bin/java');
424-
if ($downloadOk) {
418+
$this->appConfig->setValueString(Application::APP_ID, 'java_path', $extractDir . '/jdk-' . self::JAVA_URL_PATH_NAME . '-jre/bin/java');
425419
$this->writeAppSignature();
426420
}
427421
$this->removeDownloadProgress();
@@ -471,35 +465,39 @@ public function installJSignPdf(?bool $async = false): void {
471465
$this->runAsync();
472466
return;
473467
}
474-
$extractDir = $this->getFullPath() . '/' . $this->resource;
475468

476-
$downloadOk = $this->isDownloadedFilesOk();
477-
if (!$downloadOk) {
478-
$folder = $this->getEmptyFolder($this->resource);
469+
if ($this->isDownloadedFilesOk()) {
470+
// The binaries files could exists but not saved at database
471+
if (!$this->appConfig->getValueString(Application::APP_ID, 'jsignpdf_jar_path')) {
472+
$folder = $this->getFolder($this->resource);
473+
$extractDir = $this->getInternalPathOfFolder($folder);
474+
$fullPath = $extractDir . '/jsignpdf-' . JSignPdfHandler::VERSION . '/JSignPdf.jar';
475+
$this->appConfig->setValueString(Application::APP_ID, 'jsignpdf_jar_path', $fullPath);
476+
}
477+
} else {
478+
$folder = $this->getFolder($this->resource);
479479
$compressedFileName = 'jsignpdf-' . JSignPdfHandler::VERSION . '.zip';
480480
try {
481481
$compressedFile = $folder->getFile($compressedFileName);
482482
} catch (\Throwable $th) {
483483
$compressedFile = $folder->newFile($compressedFileName);
484484
}
485-
$comporessedInternalFileName = $this->getDataDir() . '/' . $this->getInternalPathOfFile($compressedFile);
485+
$comporessedInternalFileName = $this->getInternalPathOfFile($compressedFile);
486486
$url = 'https://github.com/intoolswetrust/jsignpdf/releases/download/JSignPdf_' . str_replace('.', '_', JSignPdfHandler::VERSION) . '/jsignpdf-' . JSignPdfHandler::VERSION . '.zip';
487487
/** WHEN UPDATE version: generate this hash handmade and update here */
488488
$hash = 'd239658ea50a39eb35169d8392feaffb';
489489

490490
$this->download($url, 'JSignPdf', $comporessedInternalFileName, $hash);
491491

492+
$extractDir = $this->getInternalPathOfFolder($folder);
492493
$zip = new ZIP($extractDir . '/' . $compressedFileName);
493494
$zip->extract($extractDir);
494495
unlink($extractDir . '/' . $compressedFileName);
495-
$downloadOk = true;
496-
}
497-
498-
$fullPath = $extractDir . '/jsignpdf-' . JSignPdfHandler::VERSION . '/JSignPdf.jar';
499-
$this->appConfig->setValueString(Application::APP_ID, 'jsignpdf_jar_path', $fullPath);
500-
if ($downloadOk) {
496+
$fullPath = $extractDir . '/jsignpdf-' . JSignPdfHandler::VERSION . '/JSignPdf.jar';
497+
$this->appConfig->setValueString(Application::APP_ID, 'jsignpdf_jar_path', $fullPath);
501498
$this->writeAppSignature();
502499
}
500+
503501
$this->removeDownloadProgress();
504502
}
505503

@@ -524,29 +522,28 @@ public function installPdftk(?bool $async = false): void {
524522
return;
525523
}
526524

527-
$downloadOk = $this->isDownloadedFilesOk();
528-
if ($downloadOk) {
529-
$folder = $this->getFolder($this->resource);
530-
$file = $folder->getFile('pdftk.jar');
531-
$fullPath = $this->getDataDir() . '/' . $this->getInternalPathOfFile($file);
525+
if ($this->isDownloadedFilesOk()) {
526+
// The binaries files could exists but not saved at database
527+
if (!$this->appConfig->getValueString(Application::APP_ID, 'pdftk_path')) {
528+
$folder = $this->getFolder($this->resource);
529+
$file = $folder->getFile('pdftk.jar');
530+
$fullPath = $this->getInternalPathOfFile($file);
531+
$this->appConfig->setValueString(Application::APP_ID, 'pdftk_path', $fullPath);
532+
}
532533
} else {
533-
$folder = $this->getEmptyFolder($this->resource);
534+
$folder = $this->getFolder($this->resource);
534535
try {
535536
$file = $folder->getFile('pdftk.jar');
536537
} catch (\Throwable $th) {
537538
$file = $folder->newFile('pdftk.jar');
538539
}
539-
$fullPath = $this->getDataDir() . '/' . $this->getInternalPathOfFile($file);
540+
$fullPath = $this->getInternalPathOfFile($file);
540541
$url = 'https://gitlab.com/api/v4/projects/5024297/packages/generic/pdftk-java/v' . self::PDFTK_VERSION . '/pdftk-all.jar';
541-
/** WHEN UPDATE version: generate this hash handmade and update here */
542+
/** @todo WHEN UPDATE version: generate this hash handmade and update here */
542543
$hash = '59a28bed53b428595d165d52988bf4cf';
543544

544545
$this->download($url, 'pdftk', $fullPath, $hash);
545-
$downloadOk = true;
546-
}
547-
548-
$this->appConfig->setValueString(Application::APP_ID, 'pdftk_path', $fullPath);
549-
if ($downloadOk) {
546+
$this->appConfig->setValueString(Application::APP_ID, 'pdftk_path', $fullPath);
550547
$this->writeAppSignature();
551548
}
552549
$this->removeDownloadProgress();
@@ -586,43 +583,42 @@ public function installCfssl(?bool $async = false): void {
586583
}
587584

588585
private function installCfsslByArchitecture(string $architecture): void {
589-
$downloadOk = $this->isDownloadedFilesOk();
590-
if ($downloadOk) {
591-
$folder = $this->getFolder($this->resource);
592-
} else {
593-
$folder = $this->getEmptyFolder($this->resource);
594-
$downloads = [
595-
[
596-
'file' => 'cfssl_' . self::CFSSL_VERSION . '_linux_' . $architecture,
597-
'destination' => 'cfssl',
598-
],
599-
[
600-
'file' => 'cfssljson_' . self::CFSSL_VERSION . '_linux_' . $architecture,
601-
'destination' => 'cfssljson',
602-
],
603-
];
604-
$baseUrl = 'https://github.com/cloudflare/cfssl/releases/download/v' . self::CFSSL_VERSION . '/';
605-
$checksumUrl = 'https://github.com/cloudflare/cfssl/releases/download/v' . self::CFSSL_VERSION . '/cfssl_' . self::CFSSL_VERSION . '_checksums.txt';
606-
foreach ($downloads as $download) {
607-
$hash = $this->getHash($download['file'], $checksumUrl);
608-
609-
$file = $folder->newFile($download['destination']);
610-
$fullPath = $this->getDataDir() . '/' . $this->getInternalPathOfFile($file);
611-
612-
$dependencyName = $download['destination'] . ' ' . $architecture;
613-
$this->download($baseUrl . $download['file'], $dependencyName, $fullPath, $hash, 'sha256');
614-
615-
chmod($fullPath, 0700);
586+
if ($this->isDownloadedFilesOk()) {
587+
// The binaries files could exists but not saved at database
588+
if (!$this->isCfsslBinInstalled()) {
589+
$folder = $this->getFolder($this->resource);
590+
$cfsslBinPath = $this->getInternalPathOfFolder($folder) . '/cfssl';
591+
$this->appConfig->setValueString(Application::APP_ID, 'cfssl_bin', $cfsslBinPath);
616592
}
617-
$downloadOk = true;
593+
return;
618594
}
595+
$folder = $this->getFolder($this->resource);
596+
$downloads = [
597+
[
598+
'file' => 'cfssl_' . self::CFSSL_VERSION . '_linux_' . $architecture,
599+
'destination' => 'cfssl',
600+
],
601+
[
602+
'file' => 'cfssljson_' . self::CFSSL_VERSION . '_linux_' . $architecture,
603+
'destination' => 'cfssljson',
604+
],
605+
];
606+
$baseUrl = 'https://github.com/cloudflare/cfssl/releases/download/v' . self::CFSSL_VERSION . '/';
607+
$checksumUrl = 'https://github.com/cloudflare/cfssl/releases/download/v' . self::CFSSL_VERSION . '/cfssl_' . self::CFSSL_VERSION . '_checksums.txt';
608+
foreach ($downloads as $download) {
609+
$hash = $this->getHash($download['file'], $checksumUrl);
619610

620-
$cfsslBinPath = $this->getDataDir() . '/' .
621-
$this->getInternalPathOfFolder($folder) . '/cfssl';
622-
$this->appConfig->setValueString(Application::APP_ID, 'cfssl_bin', $cfsslBinPath);
623-
if ($downloadOk) {
624-
$this->writeAppSignature();
611+
$file = $folder->newFile($download['destination']);
612+
$fullPath = $this->getInternalPathOfFile($file);
613+
614+
$dependencyName = $download['destination'] . ' ' . $architecture;
615+
$this->download($baseUrl . $download['file'], $dependencyName, $fullPath, $hash, 'sha256');
616+
617+
chmod($fullPath, 0700);
625618
}
619+
$cfsslBinPath = $this->getInternalPathOfFolder($folder) . '/cfssl';
620+
$this->appConfig->setValueString(Application::APP_ID, 'cfssl_bin', $cfsslBinPath);
621+
$this->writeAppSignature();
626622
}
627623

628624
public function uninstallCfssl(): void {

tests/Unit/Service/InstallServiceTest.php

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -143,18 +143,29 @@ public static function providerDownloadCli(): array {
143143
* @dataProvider providerGetFolder
144144
* @runInSeparateProcess
145145
*/
146-
public function testGetFolder(string $path): void {
146+
public function testGetFolder(string $architecture, string $path, string $expectedFolderName): void {
147147
$install = \OCP\Server::get(\OCA\Libresign\Service\Install\InstallService::class);
148-
self::invokePrivate($install, 'getFolder', [$path]);
149-
$this->expectNotToPerformAssertions();
148+
if (!empty($architecture)) {
149+
$install->setArchitecture($architecture);
150+
}
151+
$folder = self::invokePrivate($install, 'getFolder', [$path]);
152+
$this->assertEquals($folder->getName(), $expectedFolderName);
150153
}
151154

152155
public static function providerGetFolder(): array {
153156
return [
154-
[''],
155-
['test'],
156-
['test/folder1'],
157-
['test/folder1/folder2'],
157+
['', '', php_uname('m')],
158+
['', 'test', 'test'],
159+
['', 'test/folder1', 'folder1'],
160+
['', 'test/folder1/folder2', 'folder2'],
161+
['aarch64', '', 'aarch64'],
162+
['aarch64', 'test', 'test'],
163+
['aarch64', 'test/folder1', 'folder1'],
164+
['aarch64', 'test/folder1/folder2', 'folder2'],
165+
['x86_64', '', 'x86_64'],
166+
['x86_64', 'test', 'test'],
167+
['x86_64', 'test/folder1', 'folder1'],
168+
['x86_64', 'test/folder1/folder2', 'folder2'],
158169
];
159170
}
160171
}

0 commit comments

Comments
 (0)