Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add plugin checksums verification #26

Merged
merged 49 commits into from
Dec 22, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
f48fe77
Rename Checksum_Command into Core_Command.
schlessera Nov 22, 2017
cf5f83b
Make Core command executable.
schlessera Nov 22, 2017
ce1ffd0
Add checksum namespace.
schlessera Nov 22, 2017
00f3254
Add separate plugin command and provide base class.
schlessera Nov 22, 2017
85098d7
created plugin function same as core
prajapatisagar Nov 22, 2017
42ecdf5
Merge branch 'plugin-checksums' of github.com:wp-cli/checksum-command…
schlessera Nov 22, 2017
5f6f759
Remove copied plugin method again.
schlessera Nov 22, 2017
8d1406b
Add basic feature tests.
schlessera Nov 22, 2017
98acdeb
Provide basic plugin argument parsing.
schlessera Nov 22, 2017
b13e467
Provide "--all" paramter parsing.
schlessera Nov 22, 2017
7a37c7e
Add arguments to synopsis.
schlessera Nov 22, 2017
3321bc7
Move _read method into base class (and make it protected).
schlessera Nov 22, 2017
2e62bd1
Move recursive file retrieval into base class.
schlessera Nov 22, 2017
6ad5600
Load WordPress to execute the command, as we need access to plugin data.
schlessera Nov 22, 2017
a3cec9c
added get_plugin_checksums function
prajapatisagar Nov 24, 2017
3be5b27
Use a URL template string to build the endpoint URL.
schlessera Nov 28, 2017
aa4360e
Always use braces for conditional code.
schlessera Nov 28, 2017
13bfff3
Adapt to latest JSON file structure.
schlessera Nov 28, 2017
4981850
Iterate over plugins and fetch checksums.
schlessera Nov 28, 2017
b8df360
Fetch actual version string from plugin data.
schlessera Nov 28, 2017
49c06c6
Scaffold the remaining logic.
schlessera Nov 28, 2017
4f8fda5
Make sure either one or more plugins or the --all flag are provided.
schlessera Nov 28, 2017
04dce50
Print a warning if a plugin is being skipped because the version coul…
schlessera Nov 28, 2017
39df3ef
Print a warning if the checksums for a given plugin could not be retr…
schlessera Nov 28, 2017
43d00c2
Display found errors in several different formats.
schlessera Nov 28, 2017
ea9c177
Add beginnings of the checksum check.
schlessera Nov 29, 2017
e615c1b
Iterate over checksum values, not keys.
schlessera Nov 29, 2017
f3703da
Fix the path and file names handling.
schlessera Nov 29, 2017
5c70e99
Add MD5 calculation.
schlessera Nov 29, 2017
0bfa0c4
Add SHA-256 algorithm.
schlessera Nov 29, 2017
51f6338
Add note to supports_sha256 method.
schlessera Nov 29, 2017
6619b1e
Add handling for the --all paramter.
schlessera Nov 29, 2017
909770a
Merge branch 'master' into plugin-checksums
schlessera Dec 9, 2017
58734e9
Adapt README file.
schlessera Dec 9, 2017
3aa47eb
Fix feature tests and have them use the "Duplicate Post" plugin.
schlessera Dec 14, 2017
33d5bdb
Add test to cover soft changes against readme.txt.
schlessera Dec 14, 2017
b4f0785
Implement soft changes and --strict parameter.
schlessera Dec 14, 2017
f277f9c
Add --strict flag documentation.
schlessera Dec 14, 2017
e3ad28a
Add support for multiple checksums for a single file.
schlessera Dec 21, 2017
5c30552
Fix case mismatch in multiple checksum test.
schlessera Dec 21, 2017
454a227
Fix typo: parse -> path
schlessera Dec 21, 2017
464be76
Add a reference to why wptouch plugin is being used in tests.
schlessera Dec 22, 2017
22bc73e
Replace redundant str_replace() with direct variable reference.
schlessera Dec 22, 2017
9ef77d6
Add test for parameter logic check.
schlessera Dec 22, 2017
9251a68
Fix buggy behavior for single-file plugins.
schlessera Dec 22, 2017
73efdd4
Use `report_batch_operation_results()` to report on verified plugins.
schlessera Dec 22, 2017
9326466
Second try at fixing single-file plugin support.
schlessera Dec 22, 2017
cd77f6e
Adapt tests to reporting change.
schlessera Dec 22, 2017
1d8a74a
Fix failures count (number of unique plugins, not total failures).
schlessera Dec 22, 2017
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@ Quick links: [Using](#using) | [Installing](#installing) | [Contributing](#contr

## Using

This package implements the following commands:

### wp checksum core

Verifies WordPress files against WordPress.org's checksums.

~~~
wp checksum core [--version=<version>] [--locale=<locale>]
~~~
Expand Down Expand Up @@ -52,6 +58,40 @@ site.
Warning: File doesn't verify against checksum: wp-config-sample.php
Error: WordPress installation doesn't verify against checksums.



### wp checksum plugin

Verifies plugin files against WordPress.org's checksums.

~~~
wp checksum plugin [<plugin>...] [--all] [--strict] [--format=<format>]
~~~

**OPTIONS**

[<plugin>...]
One or more plugins to verify.

[--all]
If set, all plugins will be verified.

[--strict]
If set, even "soft changes" like readme.txt changes will trigger
checksum errors.

[--format=<format>]
Render output in a specific format.
---
default: table
options:
- table
- json
- csv
- yaml
- count
---

## Installing

This package is included with WP-CLI itself, no additional installation necessary.
Expand Down
6 changes: 5 additions & 1 deletion checksum-command.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,8 @@
require_once $autoload;
}

WP_CLI::add_command( 'checksum', 'Checksum_Command' );
WP_CLI::add_command( 'checksum core', 'Checksum_Core_Command' );
WP_CLI::add_command( 'checksum plugin', 'Checksum_Plugin_Command' );
if ( class_exists( 'WP_CLI\Dispatcher\CommandNamespace' ) ) {
WP_CLI::add_command( 'checksum', 'Checksum_Namespace' );
}
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@
},
"bundled": true,
"commands": [
"checksum core"
"checksum core",
"checksum plugin"
]
}
}
108 changes: 108 additions & 0 deletions features/checksum-plugin.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
Feature: Validate checksums for WordPress plugins

Scenario: Verify plugin checksums
Given a WP install

When I run `wp plugin install duplicate-post --version=3.2.1`
Then STDOUT should not be empty
And STDERR should be empty

When I run `wp checksum plugin duplicate-post`
Then STDOUT should be:
"""
Success: Verified 1 of 1 plugins.
"""

Scenario: Modified plugin doesn't verify
Given a WP install

When I run `wp plugin install duplicate-post --version=3.2.1`
Then STDOUT should not be empty
And STDERR should be empty

Given "Duplicate Post" replaced with "Different Name" in the wp-content/plugins/duplicate-post/duplicate-post.php file

When I try `wp checksum plugin duplicate-post --format=json`
Then STDOUT should contain:
"""
"plugin_name":"duplicate-post","file":"duplicate-post.php","message":"Checksum does not match"
"""
And STDERR should be:
"""
Error: No plugins verified (1 failed).
"""

When I run `rm wp-content/plugins/duplicate-post/duplicate-post.css`
Then STDERR should be empty

When I try `wp checksum plugin duplicate-post --format=json`
Then STDOUT should contain:
"""
"plugin_name":"duplicate-post","file":"duplicate-post.css","message":"File is missing"
"""
And STDERR should be:
"""
Error: No plugins verified (1 failed).
"""

When I run `touch wp-content/plugins/duplicate-post/additional-file.php`
Then STDERR should be empty

When I try `wp checksum plugin duplicate-post --format=json`
Then STDOUT should contain:
"""
"plugin_name":"duplicate-post","file":"additional-file.php","message":"File was added"
"""
And STDERR should be:
"""
Error: No plugins verified (1 failed).
"""

Scenario: Soft changes are only reported in strict mode
Given a WP install

When I run `wp plugin install duplicate-post --version=3.2.1`
Then STDOUT should not be empty
And STDERR should be empty

Given "Duplicate Post" replaced with "Different Name" in the wp-content/plugins/duplicate-post/readme.txt file

When I run `wp checksum plugin duplicate-post`
Then STDOUT should be:
"""
Success: Verified 1 of 1 plugins.
"""
And STDERR should be empty

When I try `wp checksum plugin duplicate-post --strict`
Then STDOUT should not be empty
And STDERR should contain:
"""
Error: No plugins verified (1 failed).
"""

# WPTouch 4.3.22 contains multiple checksums for some of its files.
# See https://github.com/wp-cli/checksum-command/issues/24
Scenario: Multiple checksums for a single file are supported
Given a WP install

When I run `wp plugin install wptouch --version=4.3.22`
Then STDOUT should not be empty
And STDERR should be empty

When I run `wp checksum plugin wptouch`
Then STDOUT should be:
"""
Success: Verified 1 of 1 plugins.
"""
And STDERR should be empty

Scenario: Throws an error if provided with neither plugin names nor the --all flag
Given a WP install

When I try `wp checksum plugin`
Then STDERR should contain:
"""
You need to specify either one or more plugin slugs to check or use the --all flag to check all plugins.
"""
And STDOUT should be empty
69 changes: 69 additions & 0 deletions src/Checksum_Base_Command.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
<?php

use \WP_CLI\Utils;

/**
* Base command that all checksum commands rely on.
*
* @package wp-cli
*/
class Checksum_Base_Command extends WP_CLI_Command {

/**
* Read a remote file and return its contents.
*
* @param string $url URL of the remote file to read.
*
* @return mixed
*/
protected static function _read( $url ) {
$headers = array( 'Accept' => 'application/json' );
$response = Utils\http_request( 'GET', $url, null, $headers,
array( 'timeout' => 30 ) );
if ( 200 === $response->status_code ) {
return $response->body;
}
WP_CLI::error( "Couldn't fetch response from {$url} (HTTP code {$response->status_code})." );
}

/**
* Recursively get the list of files for a given path.
*
* @param string $path Root path to start the recursive traversal in.
*
* @return array<string>
*/
protected function get_files( $path ) {
$filtered_files = array();
try {
$files = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator( $path,
RecursiveDirectoryIterator::SKIP_DOTS ),
RecursiveIteratorIterator::CHILD_FIRST
);
foreach ( $files as $file_info ) {
$pathname = substr( $file_info->getPathname(), strlen( $path ) );
if ( $file_info->isFile() && $this->filter_file( $pathname ) ) {
$filtered_files[] = $pathname;
}
}
} catch ( Exception $e ) {
WP_CLI::error( $e->getMessage() );
}

return $filtered_files;
}

/**
* Whether to include the file in the verification or not.
*
* Can be overridden in subclasses.
*
* @param string $filepath Path to a file.
*
* @return bool
*/
protected function filter_file( $filepath ) {
return true;
}
}
50 changes: 13 additions & 37 deletions src/Checksum_Command.php → src/Checksum_Core_Command.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,7 @@
*
* @package wp-cli
*/
class Checksum_Command extends WP_CLI_Command {

private static function _read( $url ) {
$headers = array('Accept' => 'application/json');
$response = Utils\http_request( 'GET', $url, null, $headers, array( 'timeout' => 30 ) );
if ( 200 === $response->status_code ) {
return $response->body;
} else {
WP_CLI::error( "Couldn't fetch response from {$url} (HTTP code {$response->status_code})." );
}
}
class Checksum_Core_Command extends Checksum_Base_Command {

private function get_download_offer( $locale ) {
$out = unserialize( self::_read(
Expand All @@ -32,7 +22,6 @@ private function get_download_offer( $locale ) {
return $offer;
}


/**
* Verifies WordPress files against WordPress.org's checksums.
*
Expand Down Expand Up @@ -77,7 +66,7 @@ private function get_download_offer( $locale ) {
*
* @when before_wp_load
*/
public function core( $args, $assoc_args ) {
public function __invoke( $args, $assoc_args ) {
global $wp_version, $wp_local_package;

if ( ! empty( $assoc_args['version'] ) ) {
Expand Down Expand Up @@ -124,8 +113,8 @@ public function core( $args, $assoc_args ) {
}
}

$core_checksums_files = array_filter( array_keys( $checksums ), array( $this, 'only_core_files_filter' ) );
$core_files = $this->get_wp_core_files();
$core_checksums_files = array_filter( array_keys( $checksums ), array( $this, 'filter_file' ) );
$core_files = $this->get_files( ABSPATH );
$additional_files = array_diff( $core_files, $core_checksums_files );

if ( ! empty( $additional_files ) ) {
Expand All @@ -141,28 +130,15 @@ public function core( $args, $assoc_args ) {
}
}

private function get_wp_core_files() {
$core_files = array();
try {
$files = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator( ABSPATH, RecursiveDirectoryIterator::SKIP_DOTS ),
RecursiveIteratorIterator::CHILD_FIRST
);
foreach ( $files as $file_info ) {
$pathname = substr( $file_info->getPathname(), strlen( ABSPATH ) );
if ( $file_info->isFile() && ( 0 === strpos( $pathname, 'wp-admin/' ) || 0 === strpos( $pathname, 'wp-includes/' ) ) ) {
$core_files[] = str_replace( ABSPATH, '', $file_info->getPathname() );
}
}
} catch( Exception $e ) {
WP_CLI::error( $e->getMessage() );
}

return $core_files;
}

private function only_core_files_filter( $file ) {
return ( 0 === strpos( $file, 'wp-admin/' ) || 0 === strpos( $file, 'wp-includes/' ) );
/**
* Whether to include the file in the verification or not.
*
* @param string $filepath Path to a file.
*
* @return bool
*/
protected function filter_file( $filepath ) {
return ( 0 === strpos( $filepath, 'wp-admin/' ) || 0 === strpos( $filepath, 'wp-includes/' ) );
}

/**
Expand Down
12 changes: 12 additions & 0 deletions src/Checksum_Namespace.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

use WP_CLI\Dispatcher\CommandNamespace;

/**
* Verifies file integrity by comparing to published checksums.
*
* @package wp-cli
*/
class Checksum_Namespace extends CommandNamespace {

}
Loading