diff --git a/inc/class-statifyblacklist.php b/inc/class-statifyblacklist.php index 59b071e..7bbe94c 100644 --- a/inc/class-statifyblacklist.php +++ b/inc/class-statifyblacklist.php @@ -116,6 +116,7 @@ class StatifyBlacklist { * @since 1.2.1 update_options($options = null) Parameter with default value introduced. * * @param array $options Optional. New options to save. + * * @return void */ public static function update_options( $options = null ) { @@ -181,10 +182,10 @@ class StatifyBlacklist { case self::MODE_REGEX: case self::MODE_REGEX_CI: // Merge given regular expressions into one. - $regexp = '/' . implode( '|', array_keys( self::$_options['referer']['blacklist'] ) ) . '/'; - if ( self::MODE_REGEX_CI === self::$_options['referer']['regexp'] ) { - $regexp .= 'i'; - } + $regexp = self::regex( + array_keys( self::$_options['referer']['blacklist'] ), + self::MODE_REGEX_CI === self::$_options['referer']['regexp'] + ); // Check blacklist (no return to continue filtering #12). if ( 1 === preg_match( $regexp, $referer ) ) { @@ -229,10 +230,10 @@ class StatifyBlacklist { $target = ( isset( $_SERVER['REQUEST_URI'] ) ? $_SERVER['REQUEST_URI'] : '/' ); // @codingStandardsIgnoreEnd // Merge given regular expressions into one. - $regexp = '/' . implode( '|', array_keys( self::$_options['target']['blacklist'] ) ) . '/'; - if ( 2 === self::$_options['target']['regexp'] ) { - $regexp .= 'i'; - } + $regexp = self::regex( + array_keys( self::$_options['target']['blacklist'] ), + self::MODE_REGEX_CI === self::$_options['target']['regexp'] + ); // Check blacklist (no return to continue filtering #12). if ( 1 === preg_match( $regexp, $target ) ) { @@ -268,6 +269,37 @@ class StatifyBlacklist { return null; } + /** + * Preprocess regular expression provided by the user, i.e. add delimiters and optional ci flag. + * + * @param string|array $expression Original expression string or array of expressions. + * @param string|array $case_insensitive Make expression match case-insensitive. + * + * @return string Preprocessed expression ready for preg_match(). + */ + protected static function regex( $expression, $case_insensitive ) { + $res = '/'; + if ( is_string( $expression ) ) { + $res .= str_replace( '/', '\/', $expression ); + } elseif ( is_array( $expression ) ) { + $res .= implode( + '|', + array_map( + function ( $e ) { + return str_replace( '/', '\/', $e ); + }, + $expression + ) + ); + } + $res .= '/'; + if ( $case_insensitive ) { + $res .= 'i'; + } + + return $res; + } + /** * Helper method to determine the client's IP address. * diff --git a/test/statifyblacklist-test.php b/test/statifyblacklist-test.php index b741062..4d9609f 100644 --- a/test/statifyblacklist-test.php +++ b/test/statifyblacklist-test.php @@ -617,11 +617,16 @@ class StatifyBlacklist_Test extends PHPUnit\Framework\TestCase { StatifyBlacklist::$_options['referer']['regexp'] = StatifyBlacklist::MODE_REGEX; StatifyBlacklist::$_options['referer']['blacklist'] = array( 'example\.com' => 0 ); StatifyBlacklist::$_options['target']['regexp'] = StatifyBlacklist::MODE_REGEX; - StatifyBlacklist::$_options['target']['blacklist'] = array( '\/excluded\/.*' => 0 ); + StatifyBlacklist::$_options['target']['blacklist'] = array( '/excluded/.*' => 0 ); $this->assertNull( StatifyBlacklist::apply_blacklist_filter() ); $_SERVER['HTTP_REFERER'] = 'https://example.com'; $this->assertTrue( StatifyBlacklist::apply_blacklist_filter() ); + // Check case-insensitive match. + $_SERVER['HTTP_REFERER'] = 'https://eXaMpLe.com'; + $this->assertNull( StatifyBlacklist::apply_blacklist_filter() ); + StatifyBlacklist::$_options['referer']['regexp'] = StatifyBlacklist::MODE_REGEX_CI; + $this->assertTrue( StatifyBlacklist::apply_blacklist_filter() ); $_SERVER['HTTP_REFERER'] = 'https://example.net'; $_SERVER['REQUEST_URI'] = '/excluded/page/'; $this->assertTrue( StatifyBlacklist::apply_blacklist_filter() );