Skip to content

Commit

Permalink
Merge pull request #9 from greatislander/php-7.4-compatibility
Browse files Browse the repository at this point in the history
feat: support PHP 7.4 (resolves #8)
  • Loading branch information
SteelWagstaff authored Aug 9, 2021
2 parents 139db47 + bd52cec commit e332af7
Show file tree
Hide file tree
Showing 6 changed files with 229 additions and 11 deletions.
46 changes: 46 additions & 0 deletions Pressbooks/Sniffs/ExtraSniffCode.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?php

namespace Pressbooks\Sniffs;

use PHP_CodeSniffer\Util;

trait ExtraSniffCode {
/**
* Duplicates ignore statements from a legacy sniff.
*
* This allows overriding an existing sniff and retaining the existing
* ignore statements.
*
* @param string $legacy Legacy sniff code
*/
protected function duplicate_ignores( $legacy ) {
$expression = sprintf( '/^%s(\..+)?$/', preg_quote( $legacy ) );
$base_code = Util\Common::getSniffCode( get_class( $this ) );

foreach ( $this->phpcsFile->tokenizer->ignoredLines as $line => $ignored ) {
$additional = [];

if ( empty( $ignored ) ) {
continue;
}

// Find any code which matches the legacy value.
foreach ( $ignored as $code => $value ) {
if ( preg_match( $expression, $code, $matches ) ) {
// Duplicate as the new code.
$new_code = $base_code;
if ( ! empty( $matches[1] ) ) {
$new_code .= $matches[1];
}

$additional[ $new_code ] = $value;
}
}

if ( ! empty( $additional ) ) {
$this->phpcsFile->tokenizer->ignoredLines[ $line ] = array_merge( $ignored, $additional );
}
}

}
}
68 changes: 68 additions & 0 deletions Pressbooks/Sniffs/Security/EscapeOutputSniff.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
<?php

namespace Pressbooks\Sniffs\Security;

use Pressbooks\Sniffs\ExtraSniffCode;
use PHP_CodeSniffer\Files\File as PhpcsFile;
use WordPressCS\WordPress\Sniffs\Security\EscapeOutputSniff as WPCSEscapeOutputSniff;

/**
* Verify all strings are escaped.
*
* This is subclassed from WPCS, as we need to disable warnings for error
* logging, as we don't output those to the page.
*
* @see https://github.com/WordPress/WordPress-Coding-Standards/issues/1864
*/
class EscapeOutputSniff extends WPCSEscapeOutputSniff {
use ExtraSniffCode;

/**
* Allowed functions which are treated by WPCS as printing functions.
*
* @var array
*/
protected $hmSafePrintingFunctions = [
'_deprecated_argument' => true,
'_deprecated_constructor' => true,
'_deprecated_file' => true,
'_deprecated_function' => true,
'_deprecated_hook' => true,
'_doing_it_wrong' => true,
'trigger_error' => true,
'user_error' => true,
];

/**
* Printing functions that incorporate unsafe values.
*
* This is overridden from the parent class to allow unescaped
* translated text.
*
* @var array
*/
protected $unsafePrintingFunctions = [];

/**
* Constructor.
*
* Removes non-printing functions from the property.
*/
public function __construct() {
// Remove error logging functions from output functions.
foreach ( $this->hmSafePrintingFunctions as $function => $val ) {
unset( $this->printingFunctions[ $function ] );
}
}

/**
* Override init to duplicate any ignores.
*
* @param PhpcsFile $phpcsFile
*/
protected function init( PhpcsFile $phpcsFile ) {
parent::init( $phpcsFile );

$this->duplicate_ignores( 'WordPress.Security.EscapeOutput' );
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<?php

namespace Pressbooks\Sniffs\CSRF;
namespace Pressbooks\Sniffs\Security;

class NonceVerificationSniff extends \WordPress\Sniffs\CSRF\NonceVerificationSniff {
class NonceVerificationSniff extends \WordPressCS\WordPress\Sniffs\Security\NonceVerificationSniff {

/**
* Chill out for $_GET and $_REQUEST
Expand All @@ -15,4 +15,4 @@ class NonceVerificationSniff extends \WordPress\Sniffs\CSRF\NonceVerificationSni
'$_POST' => true,
'$_FILE' => true,
];
}
}
106 changes: 106 additions & 0 deletions Pressbooks/Sniffs/Security/ValidatedSanitizedInputSniff.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
<?php

namespace Pressbooks\Sniffs\Security;

use Pressbooks\Sniffs\ExtraSniffCode;
use PHP_CodeSniffer\Files\File as PhpcsFile;
use WordPressCS\WordPress\Sniffs\Security\ValidatedSanitizedInputSniff as WPCSValidatedSanitizedInputSniff;

class ValidatedSanitizedInputSniff extends WPCSValidatedSanitizedInputSniff {
use ExtraSniffCode;

/**
* Keys to allow in the $_SERVER variable.
*
* Set this to override.
*
* @var array
*/
public $allowedServerKeys = [
'HTTP_HOST',

// User-Agent is forced to a static value when passing through
// CloudFront, so is safe to use.
'HTTP_USER_AGENT',

'HTTPS',
'REMOTE_ADDR',
'REQUEST_METHOD',
'REQUEST_TIME',
'REQUEST_TIME_FLOAT',
'REQUEST_URI',
'QUERY_STRING',
'SERVER_ADDR',
];

/**
* Override init to duplicate any ignores.
*
* @param PhpcsFile $phpcsFile
*/
protected function init( PhpcsFile $phpcsFile ) {
parent::init( $phpcsFile );

$this->duplicate_ignores( 'WordPress.Security.ValidatedSanitizedInput' );
}

/**
* Process a token for validation and sanitisation.
*
* @param int $stackPtr
* @return void
*/
public function process_token( $stackPtr ) {
// Process our custom server rules first.
if ( $this->tokens[ $stackPtr ]['content'] === '$_SERVER' ) {
$pass = $this->check_server_variable( $stackPtr );
if ( $pass ) {
// Variable is fine, skip upstream checks.
return;
}
}

// Not an allowed usage, so run the regular check on it.
return parent::process_token( $stackPtr );
}

/**
* Check whether a $_SERVER variable is constant and allowed.
*
* @param int $stackPtr Current token to check.
* @return bool True if this is a $_SERVER variable and is safe, false to run regular checks.
*/
protected function check_server_variable( $stackPtr ) {
$key = $this->get_array_access_key( $stackPtr );

// Find the next non-whitespace token.
$open_bracket = $this->phpcsFile->findNext( T_WHITESPACE, ( $stackPtr + 1 ), null, true );
if ( $this->tokens[ $open_bracket ]['code'] !== T_OPEN_SQUARE_BRACKET ) {
// No index access, run regular checks.
return false;
}

$index_token = $this->phpcsFile->findNext( T_WHITESPACE, ( $open_bracket + 1 ), null, true );
if ( $this->tokens[ $index_token ]['code'] !== T_CONSTANT_ENCAPSED_STRING ) {
// Dynamic string, run regular checks.
return false;
}

// Possible constant string, check there's no further dynamic parts.
$maybe_close_bracket = $this->phpcsFile->findNext( T_WHITESPACE, ( $index_token + 1 ), null, true );
if ( $this->tokens[ $maybe_close_bracket ]['code'] !== T_CLOSE_SQUARE_BRACKET ) {
// Dynamic string, run regular checks.
return false;
}

// Constant string, check if it's allowed.
$key = $this->strip_quotes( $this->tokens[ $index_token ]['content'] );
if ( ! in_array( $key, $this->allowedServerKeys, true ) ) {
// Unsafe key, requires sanitising.
return false;
}

// Safe key, allow it.
return true;
}
}
7 changes: 3 additions & 4 deletions Pressbooks/ruleset.xml
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,12 @@
<!-- Use HM Coding Standards -->
<rule ref="vendor/humanmade/coding-standards">
<!-- Disable rules Pressbooks overrides -->
<exclude name="WordPress.CSRF.NonceVerification.NoNonceVerification"/>
<exclude name="HM.Security"/>
<exclude name="WordPress.Security.NonceVerification"/>
<!-- Disable rules Pressbooks disagrees with: -->
<exclude name="WordPress.NamingConventions.ValidFunctionName.MethodNameInvalid"/>
<exclude name="WordPress.NamingConventions.ValidVariableName.MemberNotSnakeCase"/>
<exclude name="WordPress.NamingConventions.ValidVariableName.NotSnakeCaseMemberVar"/>
<exclude name="WordPress.VIP.SessionVariableUsage"/>
<exclude name="WordPress.VIP.SessionFunctionsUsage"/>
<exclude name="WordPress.PHP.DiscouragedPHPFunctions.system_calls_exec"/>
<exclude name="WordPress.PHP.DiscouragedPHPFunctions.runtime_configuration_ini_set"/>
<exclude name="WordPress.PHP.DiscouragedPHPFunctions.runtime_configuration_putenv"/>
Expand All @@ -37,4 +36,4 @@
<rule ref="HM.Functions.NamespacedFunctions">
<exclude-pattern>/bin/*</exclude-pattern>
</rule>
</ruleset>
</ruleset>
7 changes: 3 additions & 4 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,10 @@
"type": "project",
"license": "GPL-3.0-or-later",
"require": {
"humanmade/coding-standards": "0.5.0",
"fig-r/psr2r-sniffer": "0.5.0",
"squizlabs/php_codesniffer": "3.3.2"
"humanmade/coding-standards": "^1.0",
"squizlabs/php_codesniffer": "^3.5"
},
"require-dev": {
"phpunit/phpunit": "6.5.14"
"phpunit/phpunit": "^7.0"
}
}

0 comments on commit e332af7

Please sign in to comment.