diff --git a/.devcontainer/postCreateCommands.sh b/.devcontainer/postCreateCommands.sh index b7f0536c..1f574c89 100755 --- a/.devcontainer/postCreateCommands.sh +++ b/.devcontainer/postCreateCommands.sh @@ -6,16 +6,22 @@ sudo bash -c "docker completion bash > /usr/share/bash-completion/completions/do sudo bash -c "composer completion bash > /usr/share/bash-completion/completions/composer" sudo bash -c "npm completion > /usr/share/bash-completion/completions/npm" sudo cp xdebug.local.ini /usr/local/etc/php/conf.d/xdebug.ini +sudo cp memory.ini /usr/local/etc/php/conf.d/memory.ini sudo curl -sS https://webi.sh/gh | sh echo ". /usr/share/bash-completion/bash_completion" >> /home/vscode/.bashrc -NEXTCLOUD_VERSION=$(grep -oP "[0-9]+\.[0-9]+\.[0-9]+" install.sh) +NEXTCLOUD_VERSION=$(grep -oP -m 1 "[0-9]+\.[0-9]+\.[0-9]+" install.sh) + mkdir -p ~/.ssh/ ssh-keyscan -t rsa github.com >> ~/.ssh/known_hosts + +rm -rf nextcloud-server/ git clone --depth 1 --recurse-submodules --single-branch --branch v$NEXTCLOUD_VERSION git@github.com:nextcloud/server.git ./nextcloud-server cd nextcloud-server git submodule update --init cd - - +composer global require humbug/php-scoper +/home/vscode/.composer/vendor/bin/php-scoper completion bash >> /home/vscode/.bash_completion +echo 'export PATH=/home/vscode/.composer/vendor/bin/:$PATH' >>~/.bashrc ./install.sh \ No newline at end of file diff --git a/.github/workflows/release-app.yml b/.github/workflows/release-app.yml index 879439ca..5bff29a5 100644 --- a/.github/workflows/release-app.yml +++ b/.github/workflows/release-app.yml @@ -55,6 +55,11 @@ jobs: composer install ./vendor/bin/phpunit --bootstrap tests/unittests/bootstrap.php tests/unittests/ --testdox + - name: install php-scoper + run: | + composer global require humbug/php-scoper + echo $(composer config home --global) >> $GITHUB_PATH + - name: install nextcloud env: CLIENT_ID: ${{ secrets.VAAS_CLIENT_ID }} diff --git a/Makefile b/Makefile index 222cb8a7..d8abd510 100644 --- a/Makefile +++ b/Makefile @@ -40,7 +40,7 @@ app_directory_name=$(notdir $(CURDIR)) app_real_name=gdatavaas build_tools_directory=$(CURDIR)/build/tools -source_build_directory=$(CURDIR)/build/artifacts/source +source_build_directory=./build/artifacts/source source_package_name=$(source_build_directory)/$(app_directory_name) appstore_build_directory=$(CURDIR)/build/artifacts appstore_package_name=$(appstore_build_directory)/$(app_real_name) @@ -118,58 +118,62 @@ distclean: clean appstore: build rm -rf $(appstore_build_directory) mkdir -p $(appstore_build_directory) + php-scoper add-prefix --output-dir=$(source_build_directory) --force + mv $(source_build_directory)/vendor/netresearch/jsonmapper/src/JsonMapper/Exception.php $(source_build_directory)/vendor/netresearch/jsonmapper/src/JsonMapper/JsonMapper_Exception.php + mv $(source_build_directory)/vendor/netresearch/jsonmapper/src/JsonMapper.php $(source_build_directory)/vendor/netresearch/jsonmapper/src/JsonMapper/JsonMapper.php + composer dump-autoload --working-dir $(source_build_directory) --classmap-authoritative tar czf $(appstore_package_name).tar.gz \ - --transform s/$(app_directory_name)/$(app_real_name)/ \ + --transform s%$(source_build_directory)%$(app_real_name)% \ --exclude-vcs \ - --exclude="../$(app_directory_name)/opcache-disabled.ini" \ - --exclude="../$(app_directory_name)/opcache-blacklist.txt" \ - --exclude="../$(app_directory_name)/artifacts" \ - --exclude="../$(app_directory_name)/tmp*" \ - --exclude="../$(app_directory_name)/Dockerfile*" \ - --exclude="../$(app_directory_name)/nextcloud-server*" \ - --exclude="../$(app_directory_name)/compose-install.yaml" \ - --exclude="../$(app_directory_name)/empty-skeleton.config.php" \ - --exclude="../$(app_directory_name)/get-matrix.sh" \ - --exclude="../$(app_directory_name)/xdebug.*" \ - --exclude="../$(app_directory_name)/build" \ - --exclude="../$(app_directory_name)/tests" \ - --exclude="../$(app_directory_name)/Makefile" \ - --exclude="../$(app_directory_name)/*.log" \ - --exclude="../$(app_directory_name)/phpunit*xml" \ - --exclude="../$(app_directory_name)/composer.*" \ - --exclude="../$(app_directory_name)/node_modules" \ - --exclude="../$(app_directory_name)/js/node_modules" \ - --exclude="../$(app_directory_name)/js/tests" \ - --exclude="../$(app_directory_name)/js/test" \ - --exclude="../$(app_directory_name)/js/*.log" \ - --exclude="../$(app_directory_name)/js/package.json" \ - --exclude="../$(app_directory_name)/js/bower.json" \ - --exclude="../$(app_directory_name)/js/karma.*" \ - --exclude="../$(app_directory_name)/js/protractor.*" \ - --exclude="../$(app_directory_name)/package.json" \ - --exclude="../$(app_directory_name)/bower.json" \ - --exclude="../$(app_directory_name)/karma.*" \ - --exclude="../$(app_directory_name)/protractor\.*" \ - --exclude="../$(app_directory_name)/.*" \ - --exclude="../$(app_directory_name)/js/.*" \ - --exclude="../$(app_directory_name)/webpack.config.js" \ - --exclude="../$(app_directory_name)/stylelint.config.js" \ - --exclude="../$(app_directory_name)/CHANGELOG.md" \ - --exclude="../$(app_directory_name)/README.md" \ - --exclude="../$(app_directory_name)/package-lock.json" \ - --exclude="../$(app_directory_name)/LICENSES" \ - --exclude="../$(app_directory_name)/src" \ - --exclude="../$(app_directory_name)/babel.config.js" \ - --exclude="../$(app_directory_name)/devcontainer.yaml" \ - --exclude="../$(app_directory_name)/psalm.xml" \ - --exclude="../$(app_directory_name)/start-dev-environment.ps1" \ - --exclude="../$(app_directory_name)/start-dev-environment.sh" \ - --exclude="../$(app_directory_name)/dev-environment*" \ - --exclude="../$(app_directory_name)/install.sh" \ - --exclude="../$(app_directory_name)/renovate.json" \ - --exclude="../$(app_directory_name)/get-matrix.sh" \ - --exclude="../$(app_directory_name)/xdebug.ini" \ - --exclude="../$(app_directory_name)/compose-install.yaml" \ - --exclude="../$(app_directory_name)/Dockerfile.Nextcloud" \ - --exclude="../$(app_directory_name)/empty-skeleton.config.php" \ - ../$(app_directory_name) \ + --exclude="$(source_build_directory)/opcache-disabled.ini" \ + --exclude="$(source_build_directory)/opcache-blacklist.txt" \ + --exclude="$(source_build_directory)/artifacts" \ + --exclude="$(source_build_directory)/tmp*" \ + --exclude="$(source_build_directory)/Dockerfile*" \ + --exclude="$(source_build_directory)/nextcloud-server*" \ + --exclude="$(source_build_directory)/compose-install.yaml" \ + --exclude="$(source_build_directory)/empty-skeleton.config.php" \ + --exclude="$(source_build_directory)/get-matrix.sh" \ + --exclude="$(source_build_directory)/xdebug.*" \ + --exclude="$(source_build_directory)/build" \ + --exclude="$(source_build_directory)/tests" \ + --exclude="$(source_build_directory)/Makefile" \ + --exclude="$(source_build_directory)/*.log" \ + --exclude="$(source_build_directory)/phpunit*xml" \ + --exclude="$(source_build_directory)/composer.*" \ + --exclude="$(source_build_directory)/node_modules" \ + --exclude="$(source_build_directory)/js/node_modules" \ + --exclude="$(source_build_directory)/js/tests" \ + --exclude="$(source_build_directory)/js/test" \ + --exclude="$(source_build_directory)/js/*.log" \ + --exclude="$(source_build_directory)/js/package.json" \ + --exclude="$(source_build_directory)/js/bower.json" \ + --exclude="$(source_build_directory)/js/karma.*" \ + --exclude="$(source_build_directory)/js/protractor.*" \ + --exclude="$(source_build_directory)/package.json" \ + --exclude="$(source_build_directory)/bower.json" \ + --exclude="$(source_build_directory)/karma.*" \ + --exclude="$(source_build_directory)/protractor\.*" \ + --exclude="$(source_build_directory)/.*" \ + --exclude="$(source_build_directory)/js/.*" \ + --exclude="$(source_build_directory)/webpack.config.js" \ + --exclude="$(source_build_directory)/stylelint.config.js" \ + --exclude="$(source_build_directory)/CHANGELOG.md" \ + --exclude="$(source_build_directory)/README.md" \ + --exclude="$(source_build_directory)/package-lock.json" \ + --exclude="$(source_build_directory)/LICENSES" \ + --exclude="$(source_build_directory)/src" \ + --exclude="$(source_build_directory)/babel.config.js" \ + --exclude="$(source_build_directory)/devcontainer.yaml" \ + --exclude="$(source_build_directory)/psalm.xml" \ + --exclude="$(source_build_directory)/start-dev-environment.ps1" \ + --exclude="$(source_build_directory)/start-dev-environment.sh" \ + --exclude="$(source_build_directory)/dev-environment*" \ + --exclude="$(source_build_directory)/install.sh" \ + --exclude="$(source_build_directory)/renovate.json" \ + --exclude="$(source_build_directory)/get-matrix.sh" \ + --exclude="$(source_build_directory)/xdebug.ini" \ + --exclude="$(source_build_directory)/compose-install.yaml" \ + --exclude="$(source_build_directory)/Dockerfile.Nextcloud" \ + --exclude="$(source_build_directory)/empty-skeleton.config.php" \ + $(source_build_directory) \ diff --git a/composer.json b/composer.json index edae5c76..20870979 100644 --- a/composer.json +++ b/composer.json @@ -9,14 +9,14 @@ } ], "require": { - "gdata/vaas": "v9.0.4", + "gdata/vaas": "v9.0.5", "coduo/php-humanizer": "^5.0" }, "require-dev": { - "nextcloud/ocp": "v29.0.6", - "psalm/phar": "5.26.0", + "nextcloud/ocp": "v29.0.7", + "psalm/phar": "5.26.1", "nextcloud/coding-standard": "v1.2.3", - "phpunit/phpunit": "10.5.32", + "phpunit/phpunit": "10.5.34", "symfony/console": "6.4.11" }, "autoload": { diff --git a/empty-skeleton.config.php b/empty-skeleton.config.php index 30eef6ea..c445b487 100644 --- a/empty-skeleton.config.php +++ b/empty-skeleton.config.php @@ -2,4 +2,5 @@ $CONFIG = [ 'skeletondirectory' => '', + 'debug' => true, ]; diff --git a/install.sh b/install.sh index 86115ac6..c218463f 100755 --- a/install.sh +++ b/install.sh @@ -41,6 +41,7 @@ setup_nextcloud () { build_app () { echo "build app" + make distclean make appstore tar -xf ./build/artifacts/gdatavaas.tar.gz -C ./build/artifacts echo "build app finished" diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php index 785e27ab..29aff2de 100644 --- a/lib/AppInfo/Application.php +++ b/lib/AppInfo/Application.php @@ -53,10 +53,9 @@ public function __construct() { * @return void */ public function register(IRegistrationContext $context): void { - $composerAutoloadFile = __DIR__ . '/../../vendor/autoload.php'; - if (file_exists($composerAutoloadFile)) { - require_once $composerAutoloadFile; - } + require_once file_exists(__DIR__.'/../../vendor/scoper-autoload.php') + ? __DIR__.'/../../vendor/scoper-autoload.php' + : __DIR__.'/../../vendor/autoload.php'; // Manually register TagService so that we can customize the DI used for $silentTagMapper $context->registerService(TagService::class, function ($c) { diff --git a/lib/AvirWrapper.php b/lib/AvirWrapper.php index 7dc3e4d7..fef698f5 100644 --- a/lib/AvirWrapper.php +++ b/lib/AvirWrapper.php @@ -111,7 +111,7 @@ public function writeStream(string $path, $stream, ?int $size = null): int { public function rename($source, $target) { if ($this->shouldWrap($source)) { // After the upload apps/dav/lib/Connector/Sabre/File.php calls moveFromStorage which calls rename - $this->logger->debug(sprintf("rename(%s, %s)", $source, $target)); + $this->logger->debug(sprintf('rename(%s, %s)', $source, $target)); $this->verdictService->onRename($this->getLocalFile($source), $this->getLocalFile($target)); } return parent::rename($source, $target); @@ -135,7 +135,7 @@ private function wrapSteam(string $path, $stream) { function () use ($path, $logger) { $localPath = $this->getLocalFile($path); $filesize = $this->filesize($path); - $logger->debug("Closing " . $localPath . " with size " . $filesize); + $logger->debug('Closing ' . $localPath . ' with size ' . $filesize); if (!$this->verdictService->isAllowedToScan($localPath)) { return; @@ -162,14 +162,14 @@ function () use ($path, $logger) { } catch (UploadFailedException|ServerException) { $this->logger->error("File $localPath could not be scanned on upload with GData VaaS because there was a temporary upstream server error"); } catch (VaasAuthenticationException) { - $this->logger->error("Authentication for VaaS scan failed. Please check your credentials."); + $this->logger->error('Authentication for VaaS scan failed. Please check your credentials.'); } catch (\Exception $e) { - $this->logger->error("Unexpected error while scanning file " . $localPath . " on upload: " . $e->getMessage()); + $this->logger->error('Unexpected error while scanning file ' . $localPath . ' on upload: ' . $e->getMessage()); } - $logger->debug("Verdict for " . $localPath . " is " . $verdict->Verdict->value); + $logger->debug('Verdict for ' . $localPath . ' is ' . $verdict->Verdict->value); if ($verdict->Verdict == Verdict::MALICIOUS) { - $logger->debug("Removing malicious file " . $localPath); + $logger->debug('Removing malicious file ' . $localPath); //prevent from going to trashbin if ($this->trashEnabled) { @@ -195,7 +195,7 @@ function () use ($path, $logger) { $activity = $this->activityManager->generateEvent(); $activity->setApp(Application::APP_ID) - ->setSubject(Provider::SUBJECT_VIRUS_DETECTED_UPLOAD, [$verdict->Detection ?? "no_detection_name"]) + ->setSubject(Provider::SUBJECT_VIRUS_DETECTED_UPLOAD, [$verdict->Detection ?? 'no_detection_name']) ->setMessage(Provider::MESSAGE_FILE_DELETED) ->setObject('', 0, $path) ->setAffectedUser($owner) diff --git a/memory.ini b/memory.ini new file mode 100644 index 00000000..b0fe7fef --- /dev/null +++ b/memory.ini @@ -0,0 +1 @@ +memory_limit=-1 diff --git a/scoper.inc.php b/scoper.inc.php new file mode 100644 index 00000000..06443fad --- /dev/null +++ b/scoper.inc.php @@ -0,0 +1,135 @@ + $fileInfo->getPathName(), +// iterator_to_array( +// Finder::create()->files()->in(__DIR__), +// false, +// ), +// ); +$excludedFiles = ['templates/admin.php']; + +return [ + // The prefix configuration. If a non-null value is used, a random prefix + // will be generated instead. + // + // For more see: https://github.com/humbug/php-scoper/blob/master/docs/configuration.md#prefix + 'prefix' => 'OCA\\GDataVaas\\Vendor', + + // The base output directory for the prefixed files. + // This will be overridden by the 'output-dir' command line option if present. + 'output-dir' => null, + + // By default when running php-scoper add-prefix, it will prefix all relevant code found in the current working + // directory. You can however define which files should be scoped by defining a collection of Finders in the + // following configuration key. + // + // This configuration entry is completely ignored when using Box. + // + // For more see: https://github.com/humbug/php-scoper/blob/master/docs/configuration.md#finders-and-paths + 'finders' => [ + Finder::create() + ->files() + ->ignoreVCS(true) + ->ignoreDotFiles(true) + ->exclude([ + 'build', + '.devcontainer', + 'nextcloud-server', + 'tests', + 'tmp', + 'test', + 'examples' + ]) + ->in(__DIR__), + ], + + // List of excluded files, i.e. files for which the content will be left untouched. + // Paths are relative to the configuration file unless if they are already absolute + // + // For more see: https://github.com/humbug/php-scoper/blob/master/docs/configuration.md#patchers + 'exclude-files' => [ + // 'src/an-excluded-file.php', + ...$excludedFiles, + ], + + // PHP version (e.g. `'7.2'`) in which the PHP parser and printer will be configured into. This will affect what + // level of code it will understand and how the code will be printed. + // If none (or `null`) is configured, then the host version will be used. + 'php-version' => null, + + // When scoping PHP files, there will be scenarios where some of the code being scoped indirectly references the + // original namespace. These will include, for example, strings or string manipulations. PHP-Scoper has limited + // support for prefixing such strings. To circumvent that, you can define patchers to manipulate the file to your + // heart contents. + // + // For more see: https://github.com/humbug/php-scoper/blob/master/docs/configuration.md#patchers + 'patchers' => [ + static function (string $filePath, string $prefix, string $contents): string { + // Change the contents here. + + if (str_ends_with($filePath, 'vendor/netresearch/jsonmapper/src/JsonMapper.php') === true) { + $contents = str_replace("namespace $prefix;", "namespace $prefix\\JsonMapper;", $contents); + } + + if (str_ends_with($filePath, 'vendor/netresearch/jsonmapper/src/JsonMapper/Exception.php') === true) { + $contents = str_replace("namespace $prefix;", "namespace $prefix\\JsonMapper;", $contents); + } + + if (str_ends_with($filePath, 'vendor/gdata/vaas/Vaas.php') === true) { + $contents = str_replace('use OCA\GDataVaas\Vendor\JsonMapper', 'use OCA\GDataVaas\Vendor\JsonMapper\JsonMapper', $contents); + } + + return $contents; + }, + ], + + // List of symbols to consider internal i.e. to leave untouched. + // + // For more information see: https://github.com/humbug/php-scoper/blob/master/docs/configuration.md#excluded-symbols + 'exclude-namespaces' => [ + 'Psr', + 'OCA', + 'OCP', + 'OC\Files', + 'OC\SystemTag', + 'Symfony', + 'Icewind' + ], + 'exclude-classes' => [ + 'OC', + ], + 'exclude-functions' => [ + ], + 'exclude-constants' => [ + // 'STDIN', + ], + + // List of symbols to expose. + // + // For more information see: https://github.com/humbug/php-scoper/blob/master/docs/configuration.md#exposed-symbols + 'expose-global-constants' => false, + 'expose-global-classes' => false, + 'expose-global-functions' => false, + 'expose-namespaces' => [ + // 'Acme\Foo' // The Acme\Foo namespace (and sub-namespaces) + // '~^PHPUnit\\\\Framework$~', // The whole namespace PHPUnit\Framework (but not sub-namespaces) + // '~^$~', // The root namespace only + // '', // Any namespace + ], + 'expose-classes' => [], + 'expose-functions' => [], + 'expose-constants' => [], +];