diff --git a/.gitignore b/.gitignore index 49e8afa..03b3e8f 100644 --- a/.gitignore +++ b/.gitignore @@ -17,4 +17,5 @@ test.sh gdata-antivirus.zip test.php scoped-code/ -/svn/ \ No newline at end of file +/svn/ +eicar* \ No newline at end of file diff --git a/Infrastructure/Database/DetectedFile.php b/Infrastructure/Database/DetectedFile.php new file mode 100644 index 0000000..ae50c6e --- /dev/null +++ b/Infrastructure/Database/DetectedFile.php @@ -0,0 +1,7 @@ +get_charset_collate(); $sql = 'CREATE TABLE ' . $this->get_table_name() . ' ( file_path VARCHAR(512) NOT NULL, + detection VARCHAR(128) NOT NULL, + sha256 VARCHAR(64) NOT NULL, UNIQUE KEY file_path (file_path) )' . $charset_collate . ';'; require_once ABSPATH . 'wp-admin/includes/upgrade.php'; dbDelta($sql); wp_cache_set($this->get_table_name(), 'true', 'GdataAntivirus'); - } + } public function remove(): void { global $wpdb; @@ -64,7 +67,7 @@ public function table_exists(): bool { return false; } - public function add( string $file ): void { + public function add( DetectedFile $detected_file ): void { global $wpdb; if (! $this->table_exists()) { @@ -74,7 +77,11 @@ public function add( string $file ): void { try { $wpdb->insert( $this->get_table_name(), - array( 'file_path' => $file ) + array( + 'file_path' => $detected_file->path, + 'detection' => $detected_file->detection, + 'sha256' => $detected_file->sha256 + ) ); } catch (\Exception $e) { $this->logger->debug($e->getMessage()); @@ -93,6 +100,18 @@ public function delete( string $file ): void { ); } + public function delete_all(): void { + global $wpdb; + assert($wpdb instanceof wpdb); + + if (! $this->table_exists()) { + return; + } + $wpdb->query( + $wpdb->prepare('TRUNCATE TABLE %i', $this->get_table_name()) + ); + } + public function get_all(): array { global $wpdb; @@ -100,7 +119,7 @@ public function get_all(): array { return array(); } return $wpdb->get_results( - $wpdb->prepare('SELECT file_path FROM %i', $this->get_table_name()), + $wpdb->prepare('SELECT file_path, detection, sha256 FROM %i', $this->get_table_name()), ARRAY_A ); } diff --git a/Infrastructure/Database/IFindingsQuery.php b/Infrastructure/Database/IFindingsQuery.php index c929028..8016dec 100644 --- a/Infrastructure/Database/IFindingsQuery.php +++ b/Infrastructure/Database/IFindingsQuery.php @@ -3,8 +3,9 @@ namespace Gdatacyberdefenseag\GdataAntivirus\Infrastructure\Database; interface IFindingsQuery extends IDatabase { - public function add( string $file ): void; + public function add( DetectedFile $file ): void; public function delete( string $file ): void; + public function delete_all(): void; public function get_all(): array; public function table_exists(): bool; public function count(): int; diff --git a/PluginPage/Findings/FindingsMenuPage.php b/PluginPage/Findings/FindingsMenuPage.php index cef79a5..8a77781 100644 --- a/PluginPage/Findings/FindingsMenuPage.php +++ b/PluginPage/Findings/FindingsMenuPage.php @@ -37,6 +37,7 @@ public function __construct( add_action('admin_menu', array( $this, 'setup_menu' )); add_action('admin_post_delete_findings', array( $this, 'delete_findings' )); + add_action('admin_post_reset_findings', array( $this, 'reset_findings' )); } public function setup_menu(): void { @@ -55,6 +56,30 @@ public function validate_findings(): void { $this->findings->validate(); } + public function reset_findings(): void { + $this->logger->debug('FindingsMenuPage::reset_findings'); + if (! isset($_POST['gdata-antivirus-reset-findings-nonce'])) { + wp_die( + esc_html__('Invalid nonce specified', 'gdata-antivirus'), + esc_html__('Error', 'gdata-antivirus'), + array( + 'response' => intval(403), + ) + ); + } + if (! wp_verify_nonce(sanitize_key($_POST['gdata-antivirus-reset-findings-nonce']), 'gdata-antivirus-reset-findings')) { + wp_die( + esc_html__('Invalid nonce specified', 'gdata-antivirus'), + esc_html__('Error', 'gdata-antivirus'), + array( + 'response' => intval(403), + ) + ); + } + $this->findings->delete_all(); + wp_redirect(admin_url()); + } + public function delete_findings(): void { $this->logger->debug('FindingsMenuPage::delete_findings'); if (! isset($_POST['gdata-antivirus-delete-findings-nonce'])) { @@ -107,9 +132,15 @@ public function findings_list(): void { - + File + + Detection + + + Sha256 + @@ -134,6 +165,16 @@ public function findings_list(): void { echo esc_html($finding['file_path']); ?> + + + + + + - - + 'admin-post.php?action=delete_findings' + )); ?> + + 'admin-post.php?action=reset_findings' + )); ?> isDir()) { continue; } + // For testing purposes, we only scan files with eicar in the name + // if (str_contains($file_path->getPathname(), "eicar") === false) { + // continue; + // } $this->logger->debug($file_path->getPathname()); array_push($files, $file_path->getPathname()); if (count($files) >= $batch_size) { @@ -274,9 +279,10 @@ public function scan_batch( array $files ): void { continue; } $scan_client = $this->scan_client; - if ($scan_client->scan_file($file) === \VaasSdk\Message\Verdict::MALICIOUS) { + $vaas_verdict = $scan_client->scan_file($file); + if ($vaas_verdict->Verdict === \VaasSdk\Message\Verdict::MALICIOUS) { $this->logger->debug('add to findings ' . $file); - $this->findings->add($file); + $this->findings->add(new DetectedFile($file, $vaas_verdict->Detection, $vaas_verdict->Sha256)); } } } finally { diff --git a/Readme.md b/Readme.md index a9bc40c..637a671 100644 --- a/Readme.md +++ b/Readme.md @@ -57,6 +57,29 @@ The devcontainer is configured to mount the source code into the containers. Thi Within the devcontainer it starts a wordpress-environment with `docker composer` within that you can even debug the code running directly in wordpress. +### How to rebuild within the container + +When you change code, it is not instantly put into the container because the directory that is actually mounted is the scoped-code directory. +When starting something bigger you can just set the mount-point in the ./compose.yml and the `/var/www/html/wp-content/plugins/gdata-antivirus` in the ./.vscode/launch.json to the working directory meaning `.` or full path `/workspaces/wordpress-gdata-antivirus`. + +Doing this, you still have to test your changes with the scoped code, so basically reset your changes and rebuild the container. + +To avoid rebuilding the container on every change you can also just run the ./.devcontainer/configureWordPress.sh script with the simple `source .devcontainer/configureWordPress.sh` command. This will run the scoper and restart the composed containers. + +### Switch to live development mode + +To switch to a mode, where your changes are directly affecting the running wordpress container we provide the switch-live-develop-mode.sh script. Running this the first time will change the .vscode/launch.json and compose.yml files, so that the code in the root folder is directly mounted into the container and the debugger also points to this code (if you have a debugger running you have to restart it once). + +When running this script within a running container, you have to run `source .devcontainer/configureWordPress.sh` once to start live mode and once when you switch back to scoped mode. + +Please do not commit the code while in live mode. Just run the script again and it will reset these changes. + +### Running the cron + +If you want to run the cron event directly user this command. + +`docker exec --user www-data -it gdata-antivirus-app-1 bash -c "XDEBUG_CONFIG='client_port=9080 client_host=172.19.0.1' wp --debug cron event run gdatacyberdefenseag_antivirus_scan_batch"` + ## Disclaimer While this plugin enhances the security of your WordPress installation, no security measure is foolproof. Regular backups and other security best practices are still recommended to ensure the safety of your website. diff --git a/Readme.txt b/Readme.txt index 74b54f0..8edc3b9 100644 --- a/Readme.txt +++ b/Readme.txt @@ -56,6 +56,11 @@ While the released code is hosted on the WordPress svn, we develop the plugin on == Changelog == += 2.0.9 = +* bugfix: reconnect on long running scans +* add detection and sha256 name to upload detection +* add detection and sha256 to the findings page + = 2.0.8 = * bugfix: posts could not be saved diff --git a/Vaas/ScanClient.php b/Vaas/ScanClient.php index dbfe49c..8adacf5 100644 --- a/Vaas/ScanClient.php +++ b/Vaas/ScanClient.php @@ -8,8 +8,8 @@ use VaasSdk\Vaas; use VaasSdk\Authentication\ClientCredentialsGrantAuthenticator; use VaasSdk\Authentication\ResourceOwnerPasswordGrantAuthenticator; -use VaasSdk\Exceptions\VaasInvalidStateException; -use VaasSdk\Message\Verdict; +use VaasSdk\Message\VaasVerdict; +use VaasSdk\Message\VerdictResponse; use VaasSdk\VaasOptions as VaasParameters; if (! class_exists('ScanClient')) { @@ -102,26 +102,22 @@ public function scan_post( $data ) { $this->connect(); try { - $verdict = $this->vaas->ForStream($stream); - } catch (VaasInvalidStateException $e) { + $vaas_verdict = $this->vaas->ForStream($stream); + } catch (\Exception $e) { try { $this->reconnect(); - $verdict = $this->vaas->ForStream($stream); + $vaas_verdict = $this->vaas->ForStream($stream); } catch (\Exception $e) { $this->admin_notices->add_notice(esc_html__('virus scan failed', 'gdata-antivirus')); $this->logger->debug($e->getMessage()); return $data; } - } catch (\Exception $e) { - $this->admin_notices->add_notice(esc_html__('virus scan failed', 'gdata-antivirus')); - $this->logger->debug($e->getMessage()); - return $data; } - $this->logger->debug(var_export($verdict, true)); + $this->logger->debug(var_export($vaas_verdict->Verdict, true)); // phpcs:ignore - if (\VaasSdk\Message\Verdict::MALICIOUS === $verdict->Verdict) { + if (\VaasSdk\Message\Verdict::MALICIOUS === $vaas_verdict->Verdict) { $this->logger->debug('gdata-antivirus: virus found in post'); - wp_die(esc_html__('virus found', 'gdata-antivirus')); + wp_die(esc_html__("Virus found! - Detection: $vaas_verdict->Detection - SHA256: $vaas_verdict->Sha256 - Guid: $vaas_verdict->Guid", 'gdata-antivirus')); } return $data; } @@ -155,24 +151,21 @@ public function scan_comment( $commentdata ) { $stream = $this->file_system->get_resource_stream_from_string($commend_content); $this->connect(); try { - $verdict = $this->vaas->ForStream($stream); - } catch (VaasInvalidStateException $e) { + $vaas_verdict = $this->vaas->ForStream($stream); + } catch (\Exception $e) { try { $this->reconnect(); - $verdict = $this->vaas->ForStream($stream); + $vaas_verdict = $this->vaas->ForStream($stream); } catch (\Exception $e) { $this->admin_notices->add_notice(esc_html__('virus scan failed', 'gdata-antivirus')); $this->logger->debug($e->getMessage()); } - } catch (\Exception $e) { - $this->admin_notices->add_notice(esc_html__('virus scan failed', 'gdata-antivirus')); - $this->logger->debug($e->getMessage()); } - $this->logger->debug(var_export($verdict, true)); + $this->logger->debug(var_export($vaas_verdict->Verdict, true)); // phpcs:ignore - if (\VaasSdk\Message\Verdict::MALICIOUS === $verdict->Verdict) { + if (\VaasSdk\Message\Verdict::MALICIOUS === $vaas_verdict->Verdict) { $this->logger->debug('gdata-antivirus: virus found in comment'); - wp_die(esc_html__('virus found', 'gdata-antivirus')); + wp_die(esc_html__("Virus found! - Detection: $vaas_verdict->Detection - SHA256: $vaas_verdict->Sha256 - Guid: $vaas_verdict->Guid", 'gdata-antivirus')); } return $commentdata; } @@ -211,33 +204,31 @@ public function scan_single_upload( $file ) { } } - $verdict = $this->scan_file($file['tmp_name']); + $vaas_verdict = $this->scan_file($file['tmp_name']); + $verdict = $vaas_verdict->Verdict; if (\VaasSdk\Message\Verdict::MALICIOUS === $verdict) { - $file['error'] = __('virus found', 'gdata-antivirus'); + $file['error'] = __("Virus found! - Detection: $vaas_verdict->Detection - SHA256: $vaas_verdict->Sha256 - Guid: $vaas_verdict->Guid", 'gdata-antivirus'); } return $file; } - public function scan_file( $file_path ): Verdict { + public function scan_file( $file_path ): VaasVerdict { $this->connect(); try { - $verdict = $this->vaas->ForFile($file_path)->Verdict; - } catch (VaasInvalidStateException $e) { + $vaas_verdict = $this->vaas->ForFile($file_path); + } catch (\Exception $e) { try { $this->reconnect(); - $verdict = $this->vaas->ForFile($file_path)->Verdict; + $vaas_verdict = $this->vaas->ForFile($file_path); } catch (\Exception $e) { $this->logger->debug($e->getMessage()); - return Verdict::UNKNOWN; + return new VaasVerdict(new VerdictResponse); } - } catch (\Exception $e) { - $this->logger->debug($e->getMessage()); - return Verdict::UNKNOWN; } $this->logger->debug( - 'gdata-antivirus: verdict for file ' . $file_path . ': ' . var_export($verdict, true) + 'gdata-antivirus: verdict for file ' . $file_path . ': ' . var_export($vaas_verdict, true) ); - return $verdict; + return $vaas_verdict; } } } diff --git a/compose.yml b/compose.yml index de6487e..8defe43 100644 --- a/compose.yml +++ b/compose.yml @@ -17,6 +17,7 @@ services: WORDPRESS_DB_USER: wordpress WORDPRESS_DB_PASSWORD: wordpress WORDPRESS_TEST_DB_NAME: wordpress_test + WORDPRESS_DEBUG: true volumes: - ./scoped-code/:/var/www/html/wp-content/plugins/gdata-antivirus:ro,cached diff --git a/composer.json b/composer.json index 80e96cc..b835557 100644 --- a/composer.json +++ b/composer.json @@ -15,7 +15,7 @@ "require": { "php": ">=8.1", "gdata/vaas": "9.0.5", - "illuminate/container": "^11.27" + "illuminate/container": "^11.30" }, "config": { "platform": { @@ -32,8 +32,8 @@ }, "require-dev": { "johnpbloch/wordpress": "6.6.2", - "phpunit/phpunit": "^11.2", - "wp-coding-standards/wpcs": "^3.0", + "phpunit/phpunit": "^11.4", + "wp-coding-standards/wpcs": "^3.1", "symfony/finder": "^7.1" } -} +} \ No newline at end of file diff --git a/composer.lock b/composer.lock index acf7233..2183891 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "22fb7cfa3bf9ea3a4e65d0cab626ab40", + "content-hash": "6dbc678bbb2da49ad0fe8a69d78735ca", "packages": [ { "name": "amphp/amp", @@ -635,16 +635,16 @@ }, { "name": "amphp/parallel", - "version": "v2.2.9", + "version": "v2.3.0", "source": { "type": "git", "url": "https://github.com/amphp/parallel.git", - "reference": "73d293f1fc4df1bebc3c4fce1432e82dd7032238" + "reference": "9777db1460d1535bc2a843840684fb1205225b87" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/amphp/parallel/zipball/73d293f1fc4df1bebc3c4fce1432e82dd7032238", - "reference": "73d293f1fc4df1bebc3c4fce1432e82dd7032238", + "url": "https://api.github.com/repos/amphp/parallel/zipball/9777db1460d1535bc2a843840684fb1205225b87", + "reference": "9777db1460d1535bc2a843840684fb1205225b87", "shasum": "" }, "require": { @@ -707,7 +707,7 @@ ], "support": { "issues": "https://github.com/amphp/parallel/issues", - "source": "https://github.com/amphp/parallel/tree/v2.2.9" + "source": "https://github.com/amphp/parallel/tree/v2.3.0" }, "funding": [ { @@ -715,7 +715,7 @@ "type": "github" } ], - "time": "2024-03-24T18:27:44+00:00" + "time": "2024-09-14T19:16:14+00:00" }, { "name": "amphp/parser", @@ -1336,16 +1336,16 @@ }, { "name": "illuminate/container", - "version": "v11.27.2", + "version": "v11.30.0", "source": { "type": "git", "url": "https://github.com/illuminate/container.git", - "reference": "bc49d144a20b0d432e1ac812c9e056594b6c6480" + "reference": "06dfc614aff58384b28ba5ad191f6a02d6b192cb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/container/zipball/bc49d144a20b0d432e1ac812c9e056594b6c6480", - "reference": "bc49d144a20b0d432e1ac812c9e056594b6c6480", + "url": "https://api.github.com/repos/illuminate/container/zipball/06dfc614aff58384b28ba5ad191f6a02d6b192cb", + "reference": "06dfc614aff58384b28ba5ad191f6a02d6b192cb", "shasum": "" }, "require": { @@ -1383,11 +1383,11 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2024-10-08T13:34:53+00:00" + "time": "2024-10-11T15:30:11+00:00" }, { "name": "illuminate/contracts", - "version": "v11.27.2", + "version": "v11.30.0", "source": { "type": "git", "url": "https://github.com/illuminate/contracts.git", @@ -3425,16 +3425,16 @@ }, { "name": "phpunit/phpunit", - "version": "11.4.1", + "version": "11.4.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "7875627f15f4da7e7f0823d1f323f7295a77334e" + "reference": "e8e8ed1854de5d36c088ec1833beae40d2dedd76" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/7875627f15f4da7e7f0823d1f323f7295a77334e", - "reference": "7875627f15f4da7e7f0823d1f323f7295a77334e", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/e8e8ed1854de5d36c088ec1833beae40d2dedd76", + "reference": "e8e8ed1854de5d36c088ec1833beae40d2dedd76", "shasum": "" }, "require": { @@ -3448,21 +3448,21 @@ "phar-io/manifest": "^2.0.4", "phar-io/version": "^3.2.1", "php": ">=8.2", - "phpunit/php-code-coverage": "^11.0.6", + "phpunit/php-code-coverage": "^11.0.7", "phpunit/php-file-iterator": "^5.1.0", "phpunit/php-invoker": "^5.0.1", "phpunit/php-text-template": "^4.0.1", "phpunit/php-timer": "^7.0.1", "sebastian/cli-parser": "^3.0.2", "sebastian/code-unit": "^3.0.1", - "sebastian/comparator": "^6.1.0", + "sebastian/comparator": "^6.1.1", "sebastian/diff": "^6.0.2", "sebastian/environment": "^7.2.0", "sebastian/exporter": "^6.1.3", "sebastian/global-state": "^7.0.2", "sebastian/object-enumerator": "^6.0.1", "sebastian/type": "^5.1.0", - "sebastian/version": "^5.0.1" + "sebastian/version": "^5.0.2" }, "suggest": { "ext-soap": "To be able to generate mocks based on WSDL files" @@ -3505,7 +3505,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/11.4.1" + "source": "https://github.com/sebastianbergmann/phpunit/tree/11.4.3" }, "funding": [ { @@ -3521,7 +3521,7 @@ "type": "tidelift" } ], - "time": "2024-10-08T15:38:37+00:00" + "time": "2024-10-28T13:07:50+00:00" }, { "name": "sebastian/cli-parser", @@ -3695,16 +3695,16 @@ }, { "name": "sebastian/comparator", - "version": "6.1.0", + "version": "6.2.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "fa37b9e2ca618cb051d71b60120952ee8ca8b03d" + "reference": "43d129d6a0f81c78bee378b46688293eb7ea3739" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/fa37b9e2ca618cb051d71b60120952ee8ca8b03d", - "reference": "fa37b9e2ca618cb051d71b60120952ee8ca8b03d", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/43d129d6a0f81c78bee378b46688293eb7ea3739", + "reference": "43d129d6a0f81c78bee378b46688293eb7ea3739", "shasum": "" }, "require": { @@ -3715,12 +3715,12 @@ "sebastian/exporter": "^6.0" }, "require-dev": { - "phpunit/phpunit": "^11.3" + "phpunit/phpunit": "^11.4" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "6.1-dev" + "dev-main": "6.2-dev" } }, "autoload": { @@ -3760,7 +3760,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/comparator/issues", "security": "https://github.com/sebastianbergmann/comparator/security/policy", - "source": "https://github.com/sebastianbergmann/comparator/tree/6.1.0" + "source": "https://github.com/sebastianbergmann/comparator/tree/6.2.1" }, "funding": [ { @@ -3768,7 +3768,7 @@ "type": "github" } ], - "time": "2024-09-11T15:42:56+00:00" + "time": "2024-10-31T05:30:08+00:00" }, { "name": "sebastian/complexity", @@ -4528,16 +4528,16 @@ }, { "name": "symfony/finder", - "version": "v7.1.4", + "version": "v7.1.6", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "d95bbf319f7d052082fb7af147e0f835a695e823" + "reference": "2cb89664897be33f78c65d3d2845954c8d7a43b8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/d95bbf319f7d052082fb7af147e0f835a695e823", - "reference": "d95bbf319f7d052082fb7af147e0f835a695e823", + "url": "https://api.github.com/repos/symfony/finder/zipball/2cb89664897be33f78c65d3d2845954c8d7a43b8", + "reference": "2cb89664897be33f78c65d3d2845954c8d7a43b8", "shasum": "" }, "require": { @@ -4572,7 +4572,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v7.1.4" + "source": "https://github.com/symfony/finder/tree/v7.1.6" }, "funding": [ { @@ -4588,7 +4588,7 @@ "type": "tidelift" } ], - "time": "2024-08-13T14:28:19+00:00" + "time": "2024-10-01T08:31:23+00:00" }, { "name": "theseer/tokenizer", @@ -4709,15 +4709,15 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": {}, "prefer-stable": false, "prefer-lowest": false, "platform": { "php": ">=8.1" }, - "platform-dev": [], + "platform-dev": {}, "platform-overrides": { "php": "8.2" }, "plugin-api-version": "2.6.0" -} \ No newline at end of file +} diff --git a/scoper.inc.php b/scoper.inc.php index b20da43..e528a95 100644 --- a/scoper.inc.php +++ b/scoper.inc.php @@ -126,7 +126,8 @@ static function (string $filePath, string $prefix, string $contents): string { "SplFileInfo", "WP_Filesystem_Direct", "WP_Filesystem_Base", - "GdataAntivirusPlugin" + "GdataAntivirusPlugin", + "wpdb" ], 'exclude-functions' => [ // 'mb_str_split', diff --git a/scoper.sh b/scoper.sh index fe1b5b8..50dc520 100644 --- a/scoper.sh +++ b/scoper.sh @@ -4,7 +4,7 @@ set -e rm -rf scoped-code/ composer install --no-dev php-scoper add-prefix --force -composer install --no-dev +composer install mv scoped-code/vendor/netresearch/jsonmapper/src/JsonMapper/Exception.php scoped-code/vendor/netresearch/jsonmapper/src/JsonMapper/JsonMapper_Exception.php mv scoped-code/vendor/netresearch/jsonmapper/src/JsonMapper.php scoped-code/vendor/netresearch/jsonmapper/src/JsonMapper/JsonMapper.php diff --git a/switch-live-develop-mode.sh b/switch-live-develop-mode.sh new file mode 100644 index 0000000..a2f7ec5 --- /dev/null +++ b/switch-live-develop-mode.sh @@ -0,0 +1,19 @@ +#!/bin/bash + +if grep --fixed-strings --quiet -- '- ./scoped-code/:/var/www/html/wp-content/plugins/gdata-antivirus:ro,cached' compose.yml; +then + sed --in-place=.bak 's#/scoped-code##g' compose.yml + echo "you are now in live development mode" +else + mv compose.yml.bak compose.yml + echo "you are now in scoped development mode, make sure to run 'source .devcontainer/configureWordPress.sh' after all your changes" +fi + +if grep --fixed-strings --quiet '"/var/www/html/wp-content/plugins/gdata-antivirus": "${workspaceFolder}/scoped-code",' .vscode/launch.json; +then + sed --in-place=.bak 's#/scoped-code##g' .vscode/launch.json + echo "you can now debug the root code" +else + mv .vscode/launch.json.bak .vscode/launch.json + echo "you can now debug the scoped code" +fi \ No newline at end of file