Skip to content

Commit

Permalink
Merge pull request #1480 from nelarsen/fix_email_subject
Browse files Browse the repository at this point in the history
Fix email subject with special characters (issue 1433)](#1479
  • Loading branch information
hansmorb authored Mar 17, 2024
2 parents e221554 + ae2f9dd commit 3185b24
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 22 deletions.
20 changes: 12 additions & 8 deletions includes/TemplateParser.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,15 @@
*
* @param string $template
* @param array $objects
* @param callable $sanitizeFunction The callable used to remove unwanted tags/characters (use default 'commonsbooking_sanitizeHTML' or 'sanitize_text_field')
*
* @return mixed
*/
function commonsbooking_parse_template( string $template = '', $objects = [] ) {
function commonsbooking_parse_template( string $template = '', $objects = [], $sanitizeFunction = 'commonsbooking_sanitizeHTML' ) {
$template = preg_replace_callback(
'/\{{.*?\}}/',
function ( $match ) use ( $objects ) {
return commonsbooking_parse_template_callback( $match, $objects );
function ( $match ) use ( $objects, $sanitizeFunction ) {
return commonsbooking_parse_template_callback( $match, $objects, $sanitizeFunction );
},
$template
);
Expand All @@ -24,7 +25,7 @@ function ( $match ) use ( $objects ) {
if ( preg_match_all( '/{{.*?}}/', $template ) === 0 ) {
return apply_filters( 'commonsbooking_template_tag', $template );
} else {
return commonsbooking_parse_template( $template, $objects );
return commonsbooking_parse_template( $template, $objects, $sanitizeFunction );
}
}

Expand All @@ -41,24 +42,27 @@ function commonsbooking_parse_shortcode( $tag ) {
*
* @param mixed $match
* @param array $objects
* @param callable $sanitizeFunction The callable used to remove unwanted tags/characters
*
* @return false|mixed
*/
function commonsbooking_parse_template_callback( $match, array $objects = [] ) {
function commonsbooking_parse_template_callback( $match, array $objects = [], $sanitizeFunction = 'commonsbooking_sanitizeHTML' ) {

if ( isset( $match[0] ) ) {
$match = $match[0];

// extract the html before part, looking for {{[*] pattern
if ( preg_match( '/\{\{\[([^\]]*)\]/m', $match, $html_before ) === 1 ) {
$html_before = commonsbooking_sanitizeHTML( preg_replace( '/(\{\{)|(\}\})|(\[)|(\])/m', '', $html_before[1] ) );
$html_before = preg_replace( '/(\{\{)|(\}\})|(\[)|(\])/m', '', $html_before[1] );
$html_before = call_user_func( $sanitizeFunction, $html_before );
} else {
$html_before = '';
}

// extract the html after part looking for [*]}} pattern
if ( preg_match( '/\[([^\]]*)\]\}\}/m', $match, $html_after ) === 1 ) {
$html_after = commonsbooking_sanitizeHTML( preg_replace( '/(\{\{)|(\}\})|(\[)|(\])/m', '', $html_after[1] ) );
$html_after = preg_replace( '/(\{\{)|(\}\})|(\[)|(\])/m', '', $html_after[1] );
$html_after = call_user_func( $sanitizeFunction, $html_after );
} else {
$html_after = '';
}
Expand All @@ -81,7 +85,7 @@ function commonsbooking_parse_template_callback( $match, array $objects = [] ) {
$post = $objects[ $path[0] ];
}

$rendered_template_tag = CB::get( commonsbooking_getCBType( $path[0] ), $path[1], $post );
$rendered_template_tag = CB::get( commonsbooking_getCBType( $path[0] ), $path[1], $post, null, $sanitizeFunction );
if ( $rendered_template_tag !== null && strlen( $rendered_template_tag ) > 0 ) {
return $html_before . $rendered_template_tag . $html_after;
} else {
Expand Down
12 changes: 7 additions & 5 deletions src/CB/CB.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,12 @@ public static function getInternalDateFormat(): string {
* @param mixed $property
* @param \WP_Post|WP_User $wpObject
* @param mixed $args
* @param callable $sanitizeFunction The callable used to remove unwanted tags/characters (use default 'commonsbooking_sanitizeHTML' or 'sanitize_text_field')
*
* @return mixed
* @return Property of (custom) post (sanitized) or null if not found
* @throws Exception
*/
public static function get( $key, $property, $wpObject = null, $args = null ) {
public static function get( $key, $property, $wpObject = null, $args = null, $sanitizeFunction = "commonsbooking_sanitizeHTML" ) {

// Only CustomPost, WP_User or WP_Post ist allowed.
if ( $wpObject && ! (
Expand All @@ -49,7 +50,7 @@ public static function get( $key, $property, $wpObject = null, $args = null ) {
// If possible cast to CB Custom Post Type Model to get additional functions
$wpObject = Helper::castToCBCustomType($wpObject, $key);

$result = self::lookUp( $key, $property, $wpObject, $args ); // Find matching methods, properties or metadata
$result = self::lookUp( $key, $property, $wpObject, $args, $sanitizeFunction ); // Find matching methods, properties or metadata
$filterName = sprintf( 'commonsbooking_tag_%s_%s', $key, $property );

return apply_filters( $filterName, $result );
Expand Down Expand Up @@ -102,11 +103,12 @@ private static function getPostId( string $key ): ?int {
* @param string $property
* @param $post
* @param $args
* @param callable $sanitizeFunction The callable used to remove unwanted tags/characters
*
* @return string|null
* @throws Exception
*/
public static function lookUp( string $key, string $property, $post, $args ): ?string {
public static function lookUp( string $key, string $property, $post, $args, $sanitizeFunction ): ?string {
// in any case we need the post object, otherwise we cannot return anything
if ( ! $post ) {
return null;
Expand All @@ -120,7 +122,7 @@ public static function lookUp( string $key, string $property, $post, $args ): ?s

if ( $result ) {
// sanitize output
return commonsbooking_sanitizeHTML( $result );
return call_user_func( $sanitizeFunction, $result );
}

return $result;
Expand Down
6 changes: 4 additions & 2 deletions src/Messages/Message.php
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ public function getHeaders() {
}

public function getSubject() {
return apply_filters( 'commonsbooking_mail_subject', $this->subject, $this->getAction(), 'sanitize_text_field' );
return apply_filters( 'commonsbooking_mail_subject', $this->subject, $this->getAction() );
}

public function getBody() {
Expand Down Expand Up @@ -132,8 +132,10 @@ protected function prepareMail(
}

// parse templates & replaces template tags (e.g. {{item:name}})
// 'body' is HTML. 'subject' is not HTML needs alternative sanitation such that characters like &
// do not get converted to HTML-entities like &
$this->body = commonsbooking_sanitizeHTML( commonsbooking_parse_template( $template_body, $objects ) );
$this->subject = sanitize_text_field( commonsbooking_parse_template( $template_subject, $objects ) );
$this->subject = sanitize_text_field( commonsbooking_parse_template( $template_subject, $objects, "sanitize_text_field" ) );

// Setup mime type
$this->headers[] = "MIME-Version: 1.0";
Expand Down
14 changes: 7 additions & 7 deletions tests/php/CB/CBTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,19 +37,19 @@ class CBTest extends CustomPostTypeTest {
public function testLookUp() {
// Test if user meta value is found when handing over WP_Post object
$post = get_post( $this->postInstanceId );
$this->assertEquals( CB::lookUp( 'user', $this->userMetaKey, $post, [] ), $this->userMetaValue );
$this->assertEquals( CB::lookUp( 'user', $this->userMetaKey, $post, [], 'commonsbooking_sanitizeHTML' ), $this->userMetaValue );

// Test if post title is returned when handing over post key and post object
$this->assertEquals( CB::lookUp( 'post', 'post_title', $post, [] ), $this->postTitle );
$this->assertEquals( CB::lookUp( 'post', 'post_title', $post, [], 'commonsbooking_sanitizeHTML' ), $this->postTitle );

// Test if null is returned when trying to get not existing property of post
$this->assertEquals( null, CB::lookUp( 'user', 'post_title', $post, [] ) );
$this->assertEquals( null, CB::lookUp( 'user', 'post_title', $post, [], 'commonsbooking_sanitizeHTML' ) );

// Trying to get property without post object
$this->assertEquals( CB::lookUp( 'user', 'test', null, [] ), null );
$this->assertEquals( CB::lookUp( 'booking', 'test', null, [] ), null );
$this->assertEquals( CB::lookUp( 'item', 'test', null, [] ), null );
$this->assertEquals( CB::lookUp( 'location', 'test', null, [] ), null );
$this->assertEquals( CB::lookUp( 'user', 'test', null, [], 'commonsbooking_sanitizeHTML' ), null );
$this->assertEquals( CB::lookUp( 'booking', 'test', null, [], 'commonsbooking_sanitizeHTML' ), null );
$this->assertEquals( CB::lookUp( 'item', 'test', null, [], 'commonsbooking_sanitizeHTML' ), null );
$this->assertEquals( CB::lookUp( 'location', 'test', null, [], 'commonsbooking_sanitizeHTML' ), null );
}

public function testGet() {
Expand Down

0 comments on commit 3185b24

Please sign in to comment.