diff --git a/build/psalm-baseline.xml b/build/psalm-baseline.xml
index ffc0fc14aff15..c0f3d35e57f82 100644
--- a/build/psalm-baseline.xml
+++ b/build/psalm-baseline.xml
@@ -4619,9 +4619,6 @@
-
-
-
diff --git a/lib/private/Installer.php b/lib/private/Installer.php
index a1d27c9255bdb..f32b0e5919a2a 100644
--- a/lib/private/Installer.php
+++ b/lib/private/Installer.php
@@ -16,8 +16,8 @@
use OC\Archive\TAR;
use OC\DB\Connection;
use OC\DB\MigrationService;
+use OC\Files\FilenameValidator;
use OC_App;
-use OC_Helper;
use OCP\App\IAppManager;
use OCP\Files;
use OCP\HintException;
@@ -25,6 +25,7 @@
use OCP\IConfig;
use OCP\ITempManager;
use OCP\Migration\IOutput;
+use OCP\Server;
use phpseclib\File\X509;
use Psr\Log\LoggerInterface;
@@ -242,6 +243,10 @@ public function downloadApp(string $appId, bool $allowUnstable = false): void {
// Download the release
$tempFile = $this->tempManager->getTemporaryFile('.tar.gz');
+ if ($tempFile === false) {
+ throw new \RuntimeException('Could not create temporary file for downloading app archive.');
+ }
+
$timeout = $this->isCLI ? 0 : 120;
$client = $this->clientService->newClient();
$client->get($app['releases'][0]['download'], ['sink' => $tempFile, 'timeout' => $timeout]);
@@ -253,8 +258,11 @@ public function downloadApp(string $appId, bool $allowUnstable = false): void {
if ($verified === true) {
// Seems to match, let's proceed
$extractDir = $this->tempManager->getTemporaryFolder();
- $archive = new TAR($tempFile);
+ if ($extractDir === false) {
+ throw new \RuntimeException('Could not create temporary directory for unpacking app.');
+ }
+ $archive = new TAR($tempFile);
if (!$archive->extract($extractDir)) {
$errorMessage = 'Could not extract app ' . $appId;
@@ -329,9 +337,9 @@ public function downloadApp(string $appId, bool $allowUnstable = false): void {
// Move to app folder
if (@mkdir($baseDir)) {
$extractDir .= '/' . $folders[0];
- OC_Helper::copyr($extractDir, $baseDir);
}
- OC_Helper::copyr($extractDir, $baseDir);
+ // otherwise we just copy the outer directory
+ $this->copyRecursive($extractDir, $baseDir);
Files::rmdirr($extractDir);
return;
}
@@ -588,4 +596,33 @@ private static function includeAppScript(string $script): void {
include $script;
}
}
+
+ /**
+ * Recursive copying of local folders.
+ *
+ * @param string $src source folder
+ * @param string $dest target folder
+ */
+ private function copyRecursive(string $src, string $dest): void {
+ if (!file_exists($src)) {
+ return;
+ }
+
+ if (is_dir($src)) {
+ if (!is_dir($dest)) {
+ mkdir($dest);
+ }
+ $files = scandir($src);
+ foreach ($files as $file) {
+ if ($file != '.' && $file != '..') {
+ $this->copyRecursive("$src/$file", "$dest/$file");
+ }
+ }
+ } else {
+ $validator = Server::get(FilenameValidator::class);
+ if (!$validator->isForbidden($src)) {
+ copy($src, $dest);
+ }
+ }
+ }
}
diff --git a/lib/private/legacy/OC_Helper.php b/lib/private/legacy/OC_Helper.php
index 841433c6ea170..6caab38b78489 100644
--- a/lib/private/legacy/OC_Helper.php
+++ b/lib/private/legacy/OC_Helper.php
@@ -66,6 +66,7 @@ public static function computerFileSize(string $str): false|int|float {
* @param string $src source folder
* @param string $dest target folder
* @return void
+ * @deprecated 32.0.0 - use \OCP\Files\Folder::copy
*/
public static function copyr($src, $dest) {
if (!file_exists($src)) {
@@ -131,7 +132,7 @@ public static function canExecute($name, $path = false) {
$exts = [''];
$check_fn = 'is_executable';
// Default check will be done with $path directories :
- $dirs = explode(PATH_SEPARATOR, $path);
+ $dirs = explode(PATH_SEPARATOR, (string)$path);
// WARNING : We have to check if open_basedir is enabled :
$obd = OC::$server->get(IniGetWrapper::class)->getString('open_basedir');
if ($obd != 'none') {