Skip to content

Commit 05c1b1b

Browse files
committed
fix: prevent generate a path without existing folder
If we have a path /libresign/path/of/folder, all floders need to be exists when we send this to save the downloaded file. Signed-off-by: Vitor Mattos <vitor@php.rio>
1 parent 16fc75e commit 05c1b1b

2 files changed

Lines changed: 67 additions & 90 deletions

File tree

lib/Service/Install/InstallService.php

Lines changed: 49 additions & 83 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,8 @@ 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()) {
389376
/**
390377
* Steps to update:
391378
* Check the compatible version of Java to use JSignPdf
@@ -394,6 +381,7 @@ public function installJava(?bool $async = false): void {
394381
* URL used to get the MD5 and URL to download:
395382
* https://jdk.java.net/java-se-ri/8-MR3
396383
*/
384+
$linuxDistribution = $this->getLinuxDistributionToDownloadJava();
397385
$slugfyVersionNumber = str_replace('+', '_', self::JAVA_URL_PATH_NAME);
398386
if ($this->architecture === 'x86_64') {
399387
$compressedFileName = 'OpenJDK21U-jre_x64_' . $linuxDistribution . '_hotspot_' . $slugfyVersionNumber . '.tar.gz';
@@ -402,26 +390,24 @@ public function installJava(?bool $async = false): void {
402390
$compressedFileName = 'OpenJDK21U-jre_aarch64_' . $linuxDistribution . '_hotspot_' . $slugfyVersionNumber . '.tar.gz';
403391
$url = 'https://github.com/adoptium/temurin21-binaries/releases/download/jdk-' . self::JAVA_URL_PATH_NAME . '/' . $compressedFileName;
404392
}
405-
$checksumUrl = $url . '.sha256.txt';
406-
$hash = $this->getHash($compressedFileName, $checksumUrl);
393+
$folder = $this->getFolder('/' . $linuxDistribution . '/' . $this->resource);
407394
try {
408395
$compressedFile = $folder->getFile($compressedFileName);
409396
} catch (NotFoundException $th) {
410397
$compressedFile = $folder->newFile($compressedFileName);
411398
}
412-
$comporessedInternalFileName = $this->getDataDir() . '/' . $this->getInternalPathOfFile($compressedFile);
413399

400+
$comporessedInternalFileName = $this->getInternalPathOfFile($compressedFile);
414401
$dependencyName = 'java ' . $this->architecture . ' ' . $linuxDistribution;
402+
$checksumUrl = $url . '.sha256.txt';
403+
$hash = $this->getHash($compressedFileName, $checksumUrl);
415404
$this->download($url, $dependencyName, $comporessedInternalFileName, $hash, 'sha256');
416405

417406
$extractor = new TAR($comporessedInternalFileName);
407+
$extractDir = $this->getInternalPathOfFolder($folder);
418408
$extractor->extract($extractDir);
419409
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) {
410+
$this->appConfig->setValueString(Application::APP_ID, 'java_path', $extractDir . '/jdk-' . self::JAVA_URL_PATH_NAME . '-jre/bin/java');
425411
$this->writeAppSignature();
426412
}
427413
$this->removeDownloadProgress();
@@ -471,35 +457,31 @@ public function installJSignPdf(?bool $async = false): void {
471457
$this->runAsync();
472458
return;
473459
}
474-
$extractDir = $this->getFullPath() . '/' . $this->resource;
475460

476-
$downloadOk = $this->isDownloadedFilesOk();
477-
if (!$downloadOk) {
478-
$folder = $this->getEmptyFolder($this->resource);
461+
if (!$this->isDownloadedFilesOk()) {
462+
$folder = $this->getFolder($this->resource);
479463
$compressedFileName = 'jsignpdf-' . JSignPdfHandler::VERSION . '.zip';
480464
try {
481465
$compressedFile = $folder->getFile($compressedFileName);
482466
} catch (\Throwable $th) {
483467
$compressedFile = $folder->newFile($compressedFileName);
484468
}
485-
$comporessedInternalFileName = $this->getDataDir() . '/' . $this->getInternalPathOfFile($compressedFile);
469+
$comporessedInternalFileName = $this->getInternalPathOfFile($compressedFile);
486470
$url = 'https://github.com/intoolswetrust/jsignpdf/releases/download/JSignPdf_' . str_replace('.', '_', JSignPdfHandler::VERSION) . '/jsignpdf-' . JSignPdfHandler::VERSION . '.zip';
487471
/** WHEN UPDATE version: generate this hash handmade and update here */
488472
$hash = 'd239658ea50a39eb35169d8392feaffb';
489473

490474
$this->download($url, 'JSignPdf', $comporessedInternalFileName, $hash);
491475

476+
$extractDir = $this->getInternalPathOfFolder($folder);
492477
$zip = new ZIP($extractDir . '/' . $compressedFileName);
493478
$zip->extract($extractDir);
494479
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) {
480+
$fullPath = $extractDir . '/jsignpdf-' . JSignPdfHandler::VERSION . '/JSignPdf.jar';
481+
$this->appConfig->setValueString(Application::APP_ID, 'jsignpdf_jar_path', $fullPath);
501482
$this->writeAppSignature();
502483
}
484+
503485
$this->removeDownloadProgress();
504486
}
505487

@@ -524,29 +506,20 @@ public function installPdftk(?bool $async = false): void {
524506
return;
525507
}
526508

527-
$downloadOk = $this->isDownloadedFilesOk();
528-
if ($downloadOk) {
509+
if (!$this->isDownloadedFilesOk()) {
529510
$folder = $this->getFolder($this->resource);
530-
$file = $folder->getFile('pdftk.jar');
531-
$fullPath = $this->getDataDir() . '/' . $this->getInternalPathOfFile($file);
532-
} else {
533-
$folder = $this->getEmptyFolder($this->resource);
534511
try {
535512
$file = $folder->getFile('pdftk.jar');
536513
} catch (\Throwable $th) {
537514
$file = $folder->newFile('pdftk.jar');
538515
}
539-
$fullPath = $this->getDataDir() . '/' . $this->getInternalPathOfFile($file);
516+
$fullPath = $this->getInternalPathOfFile($file);
540517
$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 */
518+
/** @todo WHEN UPDATE version: generate this hash handmade and update here */
542519
$hash = '59a28bed53b428595d165d52988bf4cf';
543520

544521
$this->download($url, 'pdftk', $fullPath, $hash);
545-
$downloadOk = true;
546-
}
547-
548-
$this->appConfig->setValueString(Application::APP_ID, 'pdftk_path', $fullPath);
549-
if ($downloadOk) {
522+
$this->appConfig->setValueString(Application::APP_ID, 'pdftk_path', $fullPath);
550523
$this->writeAppSignature();
551524
}
552525
$this->removeDownloadProgress();
@@ -586,43 +559,36 @@ public function installCfssl(?bool $async = false): void {
586559
}
587560

588561
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);
616-
}
617-
$downloadOk = true;
562+
if ($this->isDownloadedFilesOk()) {
563+
return;
618564
}
565+
$folder = $this->getFolder($this->resource);
566+
$downloads = [
567+
[
568+
'file' => 'cfssl_' . self::CFSSL_VERSION . '_linux_' . $architecture,
569+
'destination' => 'cfssl',
570+
],
571+
[
572+
'file' => 'cfssljson_' . self::CFSSL_VERSION . '_linux_' . $architecture,
573+
'destination' => 'cfssljson',
574+
],
575+
];
576+
$baseUrl = 'https://github.com/cloudflare/cfssl/releases/download/v' . self::CFSSL_VERSION . '/';
577+
$checksumUrl = 'https://github.com/cloudflare/cfssl/releases/download/v' . self::CFSSL_VERSION . '/cfssl_' . self::CFSSL_VERSION . '_checksums.txt';
578+
foreach ($downloads as $download) {
579+
$hash = $this->getHash($download['file'], $checksumUrl);
619580

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();
581+
$file = $folder->newFile($download['destination']);
582+
$fullPath = $this->getInternalPathOfFile($file);
583+
584+
$dependencyName = $download['destination'] . ' ' . $architecture;
585+
$this->download($baseUrl . $download['file'], $dependencyName, $fullPath, $hash, 'sha256');
586+
587+
chmod($fullPath, 0700);
625588
}
589+
$cfsslBinPath = $this->getInternalPathOfFolder($folder) . '/cfssl';
590+
$this->appConfig->setValueString(Application::APP_ID, 'cfssl_bin', $cfsslBinPath);
591+
$this->writeAppSignature();
626592
}
627593

628594
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)