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 email subject with special characters (issue 1433)](https://github.com/wielebenwir/commonsbooking/pull/1479 #1480

Merged
merged 8 commits into from
Mar 17, 2024
22 changes: 13 additions & 9 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,13 +25,13 @@ 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 );
}
}

function commonsbooking_parse_shortcode( $tag ) {
$tag = (array) $tag;
return commonsbooking_parse_template_callback( $tag );
return commonsbooking_parse_template_callback( $tag, [], 'commonsbooking_sanitizeHTML' );
}

/**
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 ) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Kannst du den default Wert hier auf commonsbooking_sanitizeHTML setzen? Dann kann die Funktion auch ohne default Wert ausgeführt werden und ist sehr ähnlich zu der ursprünglichen Funktion

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gerne, habe ich eben gemacht und einmal getestet.


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 @@ -115,8 +115,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 Expand Up @@ -145,7 +147,7 @@ protected function prepareMail(
*/
public function SendNotificationMail() {
$to = apply_filters( 'commonsbooking_mail_to', $this->to, $this->action );
$subject = apply_filters( 'commonsbooking_mail_subject', $this->subject, $this->action, 'sanitize_text_field' );
$subject = apply_filters( 'commonsbooking_mail_subject', $this->subject, $this->action );
$body = apply_filters( 'commonsbooking_mail_body', $this->body, $this->action );
$attachment = apply_filters( 'commonsbooking_mail_attachment', $this->attachment, $this->action);
$headers = implode( "\r\n", $this->headers );
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