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

Fix mcrypt fatal - Removed on PHP 7.2 #159

Merged
merged 25 commits into from
Feb 11, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
a844294
Fix mcrypt fatal on data encryption
vaurdan Jul 5, 2021
e89712c
Fix error with unset `push_syndicate_settings`
vaurdan Jul 8, 2021
2997500
Add initial version of a test suite for the encryption functions.
vaurdan Jul 8, 2021
671576d
Make push_syndicate_decrypt return an array by default
vaurdan Jul 8, 2021
f3ad7a1
Use `is_string` if `assertIsString` is not available.
vaurdan Jul 8, 2021
4d5d0f4
Use `is_string` if `assertIsString` is not available.
vaurdan Jul 8, 2021
9927d42
Merge branch 'vip/deprecated-mcrypto' of github.com:Automattic/syndic…
vaurdan Jul 8, 2021
22ae798
Use `is_array` if `assertIsArray` is not available.
vaurdan Jul 8, 2021
ffa394f
Only test with `mcrypt` if the PHP version is < 7.1
vaurdan Jul 8, 2021
1f67318
Extend the PHP 7.1 validation to the encrypt and decrypt functions.
vaurdan Jul 8, 2021
5024eaa
Use yoast/wp-test-utils for compatibility with different phpunit vers…
vaurdan Jul 12, 2021
b1690a9
Refactor encryption to use Syndication_Encryption class
vaurdan Jul 19, 2021
02f0aa8
Fix tests failing on PHP 7.1
vaurdan Jul 19, 2021
8a4d2e7
Move imports and initialization to plugin root file
vaurdan Jul 20, 2021
6f09b04
Refactor tests to have individual tests for each encryptor
vaurdan Jul 20, 2021
1e6d373
Refactor tests to use a abstract test class for Encryptors
vaurdan Jul 20, 2021
8663284
Change Syndication_Encryptor to interface
vaurdan Jul 20, 2021
18fa88c
Remove leftover require_once
vaurdan Jul 20, 2021
fdb506a
Change Syndication_Encryption from a static class to an instantiable …
vaurdan Jul 21, 2021
d418b9c
Add extra validation for older PHP versions (<5.2.7), just in case.
vaurdan Jul 21, 2021
4e3873b
Remove encryptor strategy getters and setters
vaurdan Jul 23, 2021
16ec5b8
Address feedback on Encryption_Test
vaurdan Jul 23, 2021
c9f684e
Correction on the tests PHPDOC
vaurdan Jul 23, 2021
1f6b87c
Change EncryptionTest to test the `encrypt` and `decrypt` methods.
vaurdan Jul 28, 2021
9a3434d
Fix DocBlock
GaryJones Feb 11, 2024
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
26 changes: 15 additions & 11 deletions includes/class-syndication-encryption.php
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
<?php

require_once dirname( __FILE__ ) . '/class-syndication-encryptor.php';
require_once dirname( __FILE__ ) . '/class-syndication-encryptor-openssl.php';
require_once dirname( __FILE__ ) . '/class-syndication-encryptor-mcrypt.php';

/**
* Class Syndication_Encryption
*/
Expand All @@ -19,22 +15,30 @@ class Syndication_Encryption {
/**
* Returns the best possible Encryptor, given the current environment.
*
* @return Syndication_Encryptor
* @return Syndication_Encryptor|false
*/
public static function get_encryptor() {
if ( isset( self::$encryptor ) && self::$encryptor instanceof Syndication_Encryptor ) {
return self::$encryptor;
}

// On PHP 7.1 mcrypt is available, but will throw a deprecated error if its used. Therefore, checking for the
// PHP version, instead of checking for mcrypt is a better approach.
if ( version_compare( PHP_VERSION, '7.1', '<' ) ) {
self::$encryptor = new Syndication_Encryptor_MCrypt();
return false;
}

/**
* Set the Encryptor that will be used for the encryption and decryption operations.
*
* @param Syndication_Encryptor $encryptor Encryptor to be used in the encryption.
*
* @return Syndication_Encryptor|false Returns the encryptor
*/
public static function set_encryptor( $encryptor ) {
if ( $encryptor instanceof Syndication_Encryptor ) {
self::$encryptor = $encryptor;
vaurdan marked this conversation as resolved.
Show resolved Hide resolved
return self::$encryptor;
}

self::$encryptor = new Syndication_Encryptor_OpenSSL();
return self::$encryptor;
return false;
}

/**
Expand Down
6 changes: 2 additions & 4 deletions includes/class-syndication-encryptor-mcrypt.php
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
<?php

require_once dirname( __FILE__ ) . '/class-syndication-encryptor.php';

/**
* Class Syndication_Encryptor_OpenSSL
GaryJones marked this conversation as resolved.
Show resolved Hide resolved
*/
class Syndication_Encryptor_MCrypt extends Syndication_Encryptor {
class Syndication_Encryptor_MCrypt implements Syndication_Encryptor {

/**
* @inheritDoc
Expand All @@ -32,7 +30,7 @@ public function decrypt( $data, $associative = true ) {
/**
* @inheritDoc
*/
public function getCipher() {
public function get_cipher() {
return MCRYPT_RIJNDAEL_256; // phpcs:ignore PHPCompatibility.Constants.RemovedConstants.mcrypt_rijndael_256DeprecatedRemoved
}
}
10 changes: 4 additions & 6 deletions includes/class-syndication-encryptor-openssl.php
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
<?php

require_once dirname( __FILE__ ) . '/class-syndication-encryptor.php';

/**
* Class Syndication_Encryptor_OpenSSL
*/
class Syndication_Encryptor_OpenSSL extends Syndication_Encryptor {
class Syndication_Encryptor_OpenSSL implements Syndication_Encryptor {

/**
* The cipher to be used for encryption.
Expand All @@ -19,7 +17,7 @@ class Syndication_Encryptor_OpenSSL extends Syndication_Encryptor {
*/
public function encrypt( $data ) {
$data = wp_json_encode( $data );
$cipher = $this->getCipher();
$cipher = $this->get_cipher();

if ( ! $cipher ) {
return $data;
Expand All @@ -33,7 +31,7 @@ public function encrypt( $data ) {
* @inheritDoc
*/
public function decrypt( $data, $associative = true ) {
$cipher = $this->getCipher();
$cipher = $this->get_cipher();

if ( ! $cipher ) {
return $data;
Expand All @@ -51,7 +49,7 @@ public function decrypt( $data, $associative = true ) {
/**
* @inheritDoc
*/
public function getCipher() {
public function get_cipher() {
if ( in_array( $this->cipher, openssl_get_cipher_methods(), true ) ) {
return array(
'cipher' => $this->cipher,
Expand Down
27 changes: 0 additions & 27 deletions includes/class-syndication-encryptor.php

This file was deleted.

33 changes: 33 additions & 0 deletions includes/interface-syndication-encryptor.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php
GaryJones marked this conversation as resolved.
Show resolved Hide resolved

/**
* Interface Syndication_Encryptor
*/
interface Syndication_Encryptor {

/**
* Encrypts data.
*
* @param string|array $data Data to be encrypted.
*
* @return string
*/
public function encrypt( $data );

/**
* Decrypts data
*
* @param string $data Data to be decrypted.
* @param bool $associative If true, returns as an associative array. Otherwise returns as a class.
*
* @return mixed
*/
public function decrypt( $data, $associative = true );

/**
* Returns the cipher being used. It can be a string, or a array with the cipher, key and iv.
*
* @return string|array
*/
public function get_cipher();
}
28 changes: 22 additions & 6 deletions push-syndication.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,23 @@

define( 'SYNDICATION_VERSION', 2.0 );

if ( ! defined( 'PUSH_SYNDICATE_KEY' ) )
if ( ! defined( 'PUSH_SYNDICATE_KEY' ) ) {
define( 'PUSH_SYNDICATE_KEY', 'PUSH_SYNDICATE_KEY' );
}

/**
* Load syndication logger
*/
require_once( dirname( __FILE__ ) . '/includes/class-syndication-logger.php' );
require_once dirname( __FILE__ ) . '/includes/class-syndication-logger.php';
Syndication_Logger::init();

require_once( dirname( __FILE__ ) . '/includes/class-wp-push-syndication-server.php' );
require_once dirname( __FILE__ ) . '/includes/class-wp-push-syndication-server.php';

if ( defined( 'WP_CLI' ) && WP_CLI )
require_once( dirname( __FILE__ ) . '/includes/class-wp-cli.php' );
if ( defined( 'WP_CLI' ) && WP_CLI ) {
require_once dirname( __FILE__ ) . '/includes/class-wp-cli.php';
}

$GLOBALS['push_syndication_server'] = new WP_Push_Syndication_Server;
$GLOBALS['push_syndication_server'] = new WP_Push_Syndication_Server();

// Create the event counter.
require __DIR__ . '/includes/class-syndication-event-counter.php';
Expand All @@ -38,3 +40,17 @@
// Create the site auto retry functionality
require __DIR__ . '/includes/class-syndication-site-auto-retry.php';
new Failed_Syndication_Auto_Retry();

// Load encryption classes
require_once dirname( __FILE__ ) . '/includes/class-syndication-encryption.php';
require_once dirname( __FILE__ ) . '/includes/interface-syndication-encryptor.php';
require_once dirname( __FILE__ ) . '/includes/class-syndication-encryptor-mcrypt.php';
require_once dirname( __FILE__ ) . '/includes/class-syndication-encryptor-openssl.php';

// On PHP 7.1 mcrypt is available, but will throw a deprecated error if its used. Therefore, checking for the
// PHP version, instead of checking for mcrypt is a better approach.
if ( version_compare( PHP_VERSION, '7.1', '<' ) ) {
Syndication_Encryption::set_encryptor( new Syndication_Encryptor_MCrypt() );
} else {
Syndication_Encryption::set_encryptor( new Syndication_Encryptor_OpenSSL() );
}
6 changes: 6 additions & 0 deletions tests/bootstrap.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,9 @@ function _manually_load_plugin() {
*/
require_once dirname( __DIR__ ) . '/vendor/yoast/wp-test-utils/src/WPIntegration/bootstrap-functions.php';
WPIntegration\bootstrap_it();

/*
* Load tests dependencies
*/

require_once dirname( __FILE__ ) . '/class-encryptor-test-case.php';
97 changes: 97 additions & 0 deletions tests/class-encryptor-test-case.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
<?php
namespace Syndication\Tests;

use Yoast\WPTestUtils\WPIntegration\TestCase as WPIntegrationTestCase;

/**
* Class EncryptorMCryptTest
*
* @requires extension mcrypt
*/
abstract class EncryptorTestCase extends WPIntegrationTestCase {
protected $simple_string;
protected $complex_array;
protected $encryptor;

/**
* Runs before the test, set-up.
*/
public function setUp() {
$this->simple_string = 'this is a simple string!';
$this->complex_array = array(
'element' => 'this is a element',
'group' => array(
'another',
'sub',
'array',
'info' => 'test',
),
'',
145,
1 => 20.04,
3 => true,
);
}

/**
* Test a simple string encryption
*/
public function test_simple_encryption() {
$encrypted = $this->encryptor->encrypt( $this->simple_string );

self::assertIsString( $encrypted, 'assert if the string encryption returns string' );
self::assertEquals( base64_encode( base64_decode( $encrypted ) ), $encrypted, 'assert if the encrypted data is encoded in base64' );

return $encrypted;
}

/**
* Test a simple string decryption.
*
* @param string $encrypted The encrypted string from the previous test.
*
* @depends test_simple_encryption
*/
public function test_simple_decryption( $encrypted ) {
$decrypted = $this->encryptor->decrypt( $encrypted );
self::assertEquals( $this->simple_string, $decrypted );
}

/**
* Test a complex (array) encryption.
*/
public function test_complex_encryption() {
$encrypted = $this->encryptor->encrypt( $this->complex_array );

self::assertIsString( $encrypted, 'assert if the array encryption returns string' );
self::assertEquals( base64_encode( base64_decode( $encrypted ) ), $encrypted, 'assert if the encrypted data is encoded in base64' );

return $encrypted;
}

/**
* Test an array decryption.
*
* @param string $encrypted The encrypted string from the previous test.
GaryJones marked this conversation as resolved.
Show resolved Hide resolved
*
* @depends test_complex_encryption
*/
public function test_complex_decryption( $encrypted ) {
$decrypted = $this->encryptor->decrypt( $encrypted );

self::assertIsArray( $decrypted, 'assert if the decrypted data is an array' );
self::assertEquals( $this->complex_array, $decrypted, 'assert if the decrypted array is equal to the original array' );

// Test without associative set to true.
$decrypted = $this->encryptor->decrypt( $encrypted, false );
self::assertIsObject( $decrypted, 'assert if the decrypted data is an object' );
self::assertEquals( $decrypted->element, $this->complex_array['element'], 'assert if the first element is the same' );

}

/**
* Test the expected cipher
*/
abstract public function test_cipher();

}
Loading