diff --git a/includes/Checker/Checks/Plugin_Repo/File_Type_Check.php b/includes/Checker/Checks/Plugin_Repo/File_Type_Check.php index dfdc435d0..f1e547347 100644 --- a/includes/Checker/Checks/Plugin_Repo/File_Type_Check.php +++ b/includes/Checker/Checks/Plugin_Repo/File_Type_Check.php @@ -29,7 +29,8 @@ class File_Type_Check extends Abstract_File_Check { const TYPE_VCS = 4; const TYPE_HIDDEN = 8; const TYPE_APPLICATION = 16; - const TYPE_ALL = 31; // Same as all of the above with bitwise OR. + const TYPE_BADLY_NAMED = 32; + const TYPE_ALL = 63; // Same as all of the above with bitwise OR. /** * Bitwise flags to control check behavior. @@ -90,6 +91,10 @@ protected function check_files( Check_Result $result, array $files ) { if ( $this->flags & self::TYPE_APPLICATION ) { $this->look_for_application_files( $result, $files ); } + if ( $this->flags & self::TYPE_BADLY_NAMED ) { + // Check for badly named files. + $this->look_for_badly_named_files( $result, $files ); + } } /** @@ -244,6 +249,42 @@ protected function look_for_application_files( Check_Result $result, array $file } } + /** + * Looks for application files and amends the given result with an error if found. + * + * @since 1.2.0 + * + * @param Check_Result $result The check result to amend, including the plugin context to check. + * @param array $files List of absolute file paths. + */ + protected function look_for_badly_named_files( Check_Result $result, array $files ) { + $conflict_chars = '!@#$%^&*()+=[]{};:"\'<>,?/\\|`~'; + + foreach ( $files as $file ) { + $badly_name = false; + if ( preg_match( '/\s/', $file ) ) { + $badly_name = true; + } + + if ( preg_match( '/[' . preg_quote( $conflict_chars, '/' ) . ']/', basename( $file ) ) ) { + $badly_name = true; + } + + if ( $badly_name ) { + $this->add_result_error_for_file( + $result, + __( 'Badly named files are not permitted.', 'plugin-check' ), + 'badly_named_files', + $file, + 0, + 0, + '', + 8 + ); + } + } + } + /** * Gets the description for the check. * @@ -254,7 +295,7 @@ protected function look_for_application_files( Check_Result $result, array $file * @return string Description. */ public function get_description(): string { - return __( 'Detects the usage of hidden and compressed files, VCS directories, and application files.', 'plugin-check' ); + return __( 'Detects the usage of hidden and compressed files, VCS directories, application files and badly named files.', 'plugin-check' ); } /** diff --git a/tests/phpunit/testdata/plugins/test-plugin-file-type-badly-named-files-errors/badly directory/file.php b/tests/phpunit/testdata/plugins/test-plugin-file-type-badly-named-files-errors/badly directory/file.php new file mode 100644 index 000000000..5ebd0556e --- /dev/null +++ b/tests/phpunit/testdata/plugins/test-plugin-file-type-badly-named-files-errors/badly directory/file.php @@ -0,0 +1,2 @@ +,?|`~.php" "b/tests/phpunit/testdata/plugins/test-plugin-file-type-badly-named-files-errors/badly|file%name!@#$%^&*()+=[]{};:\"'<>,?|`~.php" new file mode 100644 index 000000000..92bee4abf --- /dev/null +++ "b/tests/phpunit/testdata/plugins/test-plugin-file-type-badly-named-files-errors/badly|file%name!@#$%^&*()+=[]{};:\"'<>,?|`~.php" @@ -0,0 +1,3 @@ +assertEmpty( $errors ); $this->assertSame( 0, $check_result->get_error_count() ); } + + public function test_run_with_badly_named_errors() { + // Test plugin without any forbidden file types. + $check_context = new Check_Context( UNIT_TESTS_PLUGIN_DIR . 'test-plugin-file-type-badly-named-files-errors/load.php' ); + $check_result = new Check_Result( $check_context ); + + $check = new File_Type_Check( File_Type_Check::TYPE_BADLY_NAMED ); + $check->run( $check_result ); + + $errors = $check_result->get_errors(); + + $this->assertNotEmpty( $errors ); + $this->assertEquals( 3, $check_result->get_error_count() ); + + // Check for invalid name error. + $this->assertArrayHasKey( 0, $errors['plugin name.php'] ); + $this->assertArrayHasKey( 0, $errors['plugin name.php'][0] ); + $this->assertCount( 1, wp_list_filter( $errors['plugin name.php'][0][0], array( 'code' => 'badly_named_files' ) ) ); + + // Badly named directory check. + $this->assertArrayHasKey( 0, $errors['badly directory/file.php'] ); + $this->assertArrayHasKey( 0, $errors['badly directory/file.php'][0] ); + $this->assertCount( 1, wp_list_filter( $errors['badly directory/file.php'][0][0], array( 'code' => 'badly_named_files' ) ) ); + + // Badly named file with special chars. + $this->assertArrayHasKey( 0, $errors['badly|file%name!@#$%^&*()+=[]{};:"\'<>,?|`~.php'] ); + $this->assertArrayHasKey( 0, $errors['badly|file%name!@#$%^&*()+=[]{};:"\'<>,?|`~.php'][0] ); + $this->assertCount( 1, wp_list_filter( $errors['badly|file%name!@#$%^&*()+=[]{};:"\'<>,?|`~.php'][0][0], array( 'code' => 'badly_named_files' ) ) ); + } }