--- a/interactions/dist/editor.asset.php
+++ b/interactions/dist/editor.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('lodash', 'react', 'react-jsx-runtime', 'wp-api-fetch', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-compose', 'wp-data', 'wp-element', 'wp-hooks', 'wp-i18n', 'wp-plugins', 'wp-primitives'), 'version' => 'ef6ecaa8f5a7a808aeef');
+<?php return array('dependencies' => array('lodash', 'react', 'react-jsx-runtime', 'wp-api-fetch', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-compose', 'wp-data', 'wp-element', 'wp-hooks', 'wp-i18n', 'wp-plugins', 'wp-primitives'), 'version' => '194856cd4acf728b1a09');
--- a/interactions/dist/frontend.asset.php
+++ b/interactions/dist/frontend.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array(), 'version' => '6b242d784da97c260317');
+<?php return array('dependencies' => array(), 'version' => 'f33389cbb6ef2dfc5fee');
--- a/interactions/dist/frontend/actions/cssRule.php
+++ b/interactions/dist/frontend/actions/cssRule.php
@@ -10,7 +10,7 @@
ob_start();
?>
-InteractRunner.addActionConfig({cssRule:{initAction:e=>{var t=e.getValue("property"),i=()=>e.getValue("value",e.getValue("property"));if(CSS.supports(t,i())||CSS.supports(t,i()+"px"))return e.initActionAnimation({[t]:i,onBegin:e=>e.refresh()})},initialStyles:e=>`${e.getValue("property")}: ${e.getValue("value")};`}});
+InteractRunner.addActionConfig({cssRule:{initAction:e=>{var t=e.getValue("property"),i=e.getValue("value",e.getValue("property"));if(CSS.supports(t,i)||CSS.supports(t,i+"px"))return e.initActionAnimation({[t]:i,onBegin:e=>e.refresh()})},initialStyles:e=>`${e.getValue("property")}: ${e.getValue("value")};`}});
<?php
return ob_get_clean();
No newline at end of file
--- a/interactions/interactions.php
+++ b/interactions/interactions.php
@@ -7,7 +7,7 @@
* Author URI: http://gambit.ph
* License: GPLv2 or later
* Text Domain: interactions
- * Version: 1.3.1
+ * Version: 1.3.2
*
* @fs_premium_only /freemius.php, /freemius/
*/
@@ -18,7 +18,7 @@
}
defined( 'INTERACT_BUILD' ) || define( 'INTERACT_BUILD', 'free' );
-defined( 'INTERACT_VERSION' ) || define( 'INTERACT_VERSION', '1.3.1' );
+defined( 'INTERACT_VERSION' ) || define( 'INTERACT_VERSION', '1.3.2' );
defined( 'INTERACT_FILE' ) || define( 'INTERACT_FILE', __FILE__ );
/**
--- a/interactions/src/action-types/abstract-action-type.php
+++ b/interactions/src/action-types/abstract-action-type.php
@@ -256,5 +256,155 @@
return $action;
}
+
+ /**
+ * Sanitizes the action's value before saving.
+ *
+ * Override this in a child class to implement specific sanitization.
+ *
+ * @param mixed $value The action value to sanitize.
+ * @return mixed The sanitized action value.
+ */
+ public function sanitize_data_for_saving( $value ) {
+ // By default, no sanitization is applied.
+ return $value;
+ }
+
+ /**
+ * Remove any `expression(...)` and `javascript:` content from a CSS style string for security.
+ *
+ * @param string $string
+ * @return string
+ */
+ public function sanitize_style_value( $string ) {
+ if ( ! is_string( $string ) ) {
+ return $string;
+ }
+ // Remove all expression(...) (case-insensitive).
+ $string = preg_replace( '/expressions*((?:[^()]|(?R))*)/i', '', $string );
+
+ // Remove all javascript: URIs (case-insensitive).
+ $string = preg_replace( '/javascripts*:/i', '', $string );
+
+ return $string;
+ }
+
+ /**
+ * Detect if an HTML tag is considered dangerous (can execute scripts or
+ * otherwise modify page behavior).
+ *
+ * @param string $tag_name
+ * @return bool
+ */
+ public function is_dangerous_tag( $tag_name ) {
+ if ( empty( $tag_name ) || ! is_string( $tag_name ) ) {
+ return false;
+ }
+
+ $tag_name = strtolower( trim( $tag_name ) );
+
+ // Tags that can execute scripts or modify page behavior
+ $dangerous_tags = [
+ 'script',
+ 'iframe',
+ 'object',
+ 'embed',
+ 'applet',
+ 'meta',
+ 'link',
+ 'style',
+ 'base',
+ 'form',
+ ];
+
+ return in_array( $tag_name, $dangerous_tags, true );
+ }
+
+ /**
+ * Detect if an HTML attribute is considered dangerous (event handlers,
+ * attributes that can contain JS URIs, form actions, etc.).
+ *
+ * @param string $attribute_name
+ * @return bool
+ */
+ public function is_dangerous_attribute( $attribute_name ) {
+ if ( empty( $attribute_name ) || ! is_string( $attribute_name ) ) {
+ return false;
+ }
+
+ $attribute_name = strtolower( trim( $attribute_name ) );
+
+ // Event handler attributes (onclick, onerror, onload, etc.)
+ if ( preg_match( '/^on[a-z]+/', $attribute_name ) ) {
+ return true;
+ }
+
+ // Attributes that can contain JavaScript URIs or code
+ $dangerous_attributes = [
+ 'href',
+ 'src',
+ 'action',
+ 'formaction',
+ 'form',
+ 'formmethod',
+ 'formtarget',
+ ];
+
+ return in_array( $attribute_name, $dangerous_attributes, true );
+ }
+
+ /**
+ * Validate an HTML snippet for dangerous tags, attributes or protocols.
+ * Returns true when safe, or a WP_Error describing the violation.
+ *
+ * @param string $html
+ * @return true|WP_Error
+ */
+ public function validate_html_for_saving( $html ) {
+ if ( ! is_string( $html ) ) {
+ return new WP_Error(
+ 'invalid_html',
+ __( 'HTML must be a string.', 'interactions' )
+ );
+ }
+
+ // Detect dangerous tags
+ if ( preg_match_all( '/<s*([a-z0-9-]+)/i', $html, $matches ) ) {
+ foreach ( $matches[1] as $tag ) {
+ if ( $this->is_dangerous_tag( $tag ) ) {
+ return new WP_Error(
+ 'invalid_tag',
+ sprintf( __( 'The HTML tag "%s" is not allowed.', 'interactions' ), esc_html( $tag ) )
+ );
+ }
+ }
+ }
+
+ // Detect dangerous attributes
+ if ( preg_match_all( '/<[^>]+>/i', $html, $tagMatches ) ) {
+ foreach ( $tagMatches[0] as $tagString ) {
+ if ( preg_match_all( '/([a-zA-Z0-9:-]+)s*=s*(?:"[^"]*"|'[^']*'|[^s>]+)/i', $tagString, $attrMatches ) ) {
+ foreach ( $attrMatches[1] as $attr ) {
+ if ( $this->is_dangerous_attribute( $attr ) ) {
+ return new WP_Error(
+ 'invalid_attribute',
+ sprintf( __( 'The HTML attribute "%s" is not allowed.', 'interactions' ), esc_html( $attr ) )
+ );
+ }
+ }
+ }
+ }
+ }
+
+ // Detect disallowed protocols
+ if ( preg_match( '/javascript:s*/i', $html ) || preg_match( '/data:s*text//i', $html ) ) {
+ return new WP_Error(
+ 'invalid_protocol',
+ __( 'The HTML contains disallowed protocols (javascript: or data:).', 'interactions' )
+ );
+ }
+
+ return true;
+ }
}
}
--- a/interactions/src/action-types/class-action-type-background-color.php
+++ b/interactions/src/action-types/class-action-type-background-color.php
@@ -52,6 +52,13 @@
// return parent::initilize_action( $action, $animation_data );
// }
+
+ public function sanitize_data_for_saving( $value ) {
+ if ( is_array( $value ) && isset( $value['color'] ) ) {
+ $value['color'] = $this->sanitize_style_value( $value['color'] );
+ }
+ return $value;
+ }
}
interact_add_action_type( 'backgroundColor', 'Interact_Action_Type_Background_Color' );
--- a/interactions/src/action-types/class-action-type-background-image.php
+++ b/interactions/src/action-types/class-action-type-background-image.php
@@ -33,6 +33,13 @@
$this->has_dynamic = false;
}
+
+ public function sanitize_data_for_saving( $value ) {
+ if ( is_array( $value ) && isset( $value['image'] ) ) {
+ $value['image'] = $this->sanitize_style_value( $value['image'] );
+ }
+ return $value;
+ }
}
interact_add_action_type( 'backgroundImage', 'Interact_Action_Type_Background_Image' );
--- a/interactions/src/action-types/class-action-type-css-rule.php
+++ b/interactions/src/action-types/class-action-type-css-rule.php
@@ -40,6 +40,13 @@
],
];
}
+
+ public function sanitize_data_for_saving( $value ) {
+ if ( is_array( $value ) && isset( $value['value'] ) ) {
+ $value['value'] = $this->sanitize_style_value( $value['value'] );
+ }
+ return $value;
+ }
}
interact_add_action_type( 'cssRule', 'Interact_Action_Type_Css_Rule' );
--- a/interactions/src/action-types/class-action-type-display.php
+++ b/interactions/src/action-types/class-action-type-display.php
@@ -55,6 +55,29 @@
$this->has_duration = false;
$this->has_easing = false;
}
+
+ public function sanitize_data_for_saving( $value ) {
+ if ( is_array( $value ) && isset( $value['display'] ) ) {
+ $allowed_values = [
+ 'block',
+ 'none',
+ 'inline',
+ 'inline-block',
+ 'flex',
+ 'inline-flex',
+ 'grid',
+ 'inline-grid',
+ 'initial',
+ 'inherit',
+ 'revert',
+ 'unset',
+ ];
+ if ( ! in_array( $value['display'], $allowed_values, true ) ) {
+ $value['display'] = 'block';
+ }
+ }
+ return $value;
+ }
}
interact_add_action_type( 'display', 'Interact_Action_Type_Display' );
--- a/interactions/src/action-types/class-action-type-move.php
+++ b/interactions/src/action-types/class-action-type-move.php
@@ -58,6 +58,21 @@
$this->has_dynamic = false;
}
+
+ public function sanitize_data_for_saving( $value ) {
+ // Ensure x, y, z are sanitized as numeric (including negatives and decimals), otherwise set to null (but leave blank as is)
+ foreach ( [ 'x', 'y', 'z' ] as $key ) {
+ if ( isset( $value[ $key ] ) && $value[ $key ] !== '' ) {
+ // Allow negative/positive/decimal
+ if ( is_numeric( $value[ $key ] ) ) {
+ $value[ $key ] = $value[ $key ] + 0; // Cast to int or float
+ } else {
+ $value[ $key ] = null;
+ }
+ }
+ }
+ return $value;
+ }
}
interact_add_action_type( 'move', 'Interact_Action_Type_Move' );
--- a/interactions/src/action-types/class-action-type-opacity.php
+++ b/interactions/src/action-types/class-action-type-opacity.php
@@ -36,6 +36,17 @@
$this->has_dynamic = false;
}
+
+ public function sanitize_data_for_saving( $value ) {
+ if ( is_array( $value ) && isset( $value['opacity'] ) ) {
+ if ( is_numeric( $value['opacity'] ) ) {
+ $value['opacity'] = $value['opacity'] + 0;
+ } else {
+ $value['opacity'] = null;
+ }
+ }
+ return $value;
+ }
}
interact_add_action_type( 'opacity', 'Interact_Action_Type_Opacity' );
--- a/interactions/src/action-types/class-action-type-redirect-to-url.php
+++ b/interactions/src/action-types/class-action-type-redirect-to-url.php
@@ -37,6 +37,17 @@
$this->has_easing = false;
$this->has_preview = false;
}
+
+ public function sanitize_data_for_saving( $value ) {
+ if ( is_array( $value ) && isset( $value['url'] ) ) {
+ if ( is_string( $value['url'] ) ) {
+ $value['url'] = esc_url( $value['url'] );
+ } else {
+ $value['url'] = null;
+ }
+ }
+ return $value;
+ }
}
interact_add_action_type( 'redirectToUrl', 'Interact_Action_Type_Redirect_To_Url' );
--- a/interactions/src/action-types/class-action-type-rotate.php
+++ b/interactions/src/action-types/class-action-type-rotate.php
@@ -47,7 +47,7 @@
[ 'label' => __( 'Bottom Right', 'interactions' ), 'value' => 'bottom right' ],
[ 'label' => __( 'Custom', 'interactions' ), 'value' => 'custom' ],
],
- 'default' => 'block',
+ 'default' => 'center',
],
'customTransformOrigin' => [
'name' => __( 'Custom Transform Origin', 'interactions' ),
@@ -63,6 +63,39 @@
$this->has_dynamic = false;
}
+
+ public function sanitize_data_for_saving( $value ) {
+ if ( is_array( $value ) && isset( $value['rotate'] ) ) {
+ if ( is_numeric( $value['rotate'] ) ) {
+ $value['rotate'] = $value['rotate'] + 0;
+ } else {
+ $value['rotate'] = null;
+ }
+ }
+
+ if ( is_array( $value ) && isset( $value['transformOrigin'] ) ) {
+ $allowed_transform_origins = [
+ 'center',
+ 'top',
+ 'right',
+ 'bottom',
+ 'left',
+ 'top left',
+ 'top right',
+ 'bottom left',
+ 'bottom right',
+ 'custom',
+ ];
+ if ( ! in_array( $value['transformOrigin'], $allowed_transform_origins, true ) ) {
+ $value['transformOrigin'] = 'center';
+ }
+ }
+
+ if ( isset( $value['customTransformOrigin'] ) ) {
+ $value['customTransformOrigin'] = $this->sanitize_style_value( $value['customTransformOrigin'] );
+ }
+ return $value;
+ }
}
interact_add_action_type( 'rotate', 'Interact_Action_Type_Rotate' );
--- a/interactions/src/action-types/class-action-type-scale.php
+++ b/interactions/src/action-types/class-action-type-scale.php
@@ -46,6 +46,24 @@
$this->has_dynamic = false;
}
+
+ public function sanitize_data_for_saving( $value ) {
+ if ( is_array( $value ) && isset( $value['x'] ) ) {
+ if ( is_numeric( $value['x'] ) ) {
+ $value['x'] = $value['x'] + 0;
+ } else {
+ $value['x'] = null;
+ }
+ }
+ if ( is_array( $value ) && isset( $value['y'] ) ) {
+ if ( is_numeric( $value['y'] ) ) {
+ $value['y'] = $value['y'] + 0;
+ } else {
+ $value['y'] = null;
+ }
+ }
+ return $value;
+ }
}
interact_add_action_type( 'scale', 'Interact_Action_Type_Scale' );
--- a/interactions/src/action-types/class-action-type-skew.php
+++ b/interactions/src/action-types/class-action-type-skew.php
@@ -46,6 +46,24 @@
$this->has_dynamic = false;
}
+
+ public function sanitize_data_for_saving( $value ) {
+ if ( is_array( $value ) && isset( $value['x'] ) ) {
+ if ( is_numeric( $value['x'] ) ) {
+ $value['x'] = $value['x'] + 0;
+ } else {
+ $value['x'] = null;
+ }
+ }
+ if ( is_array( $value ) && isset( $value['y'] ) ) {
+ if ( is_numeric( $value['y'] ) ) {
+ $value['y'] = $value['y'] + 0;
+ } else {
+ $value['y'] = null;
+ }
+ }
+ return $value;
+ }
}
interact_add_action_type( 'skew', 'Interact_Action_Type_Skew' );
--- a/interactions/src/action-types/class-action-type-text-color.php
+++ b/interactions/src/action-types/class-action-type-text-color.php
@@ -34,6 +34,13 @@
$this->has_dynamic = false;
}
+
+ public function sanitize_data_for_saving( $value ) {
+ if ( is_array( $value ) && isset( $value['color'] ) ) {
+ $value['color'] = $this->sanitize_style_value( $value['color'] );
+ }
+ return $value;
+ }
}
interact_add_action_type( 'textColor', 'Interact_Action_Type_Text_Color' );
--- a/interactions/src/action-types/class-action-type-toggle-class.php
+++ b/interactions/src/action-types/class-action-type-toggle-class.php
@@ -35,14 +35,14 @@
'name' => 'Action',
'type' => 'select',
'default' => 'add',
- 'options' => [
- // Translators: %s is the word 'class'.
- [ 'value' => 'add', 'label' => sprintf( __( 'Add %s', 'interactions' ), __( 'class', 'interactions' ) ) ],
- // Translators: %s is the word 'class'.
- [ 'value' => 'remove', 'label' => sprintf( __( 'Remove %s', 'interactions' ), __( 'class', 'interactions' ) ) ],
- // Translators: %s is the word 'class'.
- [ 'value' => 'toggle', 'label' => sprintf( __( 'Toggle %s', 'interactions' ), __( 'class', 'interactions' ) ) ],
- ]
+ 'options' => [
+ // Translators: %s is the word 'class'.
+ [ 'value' => 'add', 'label' => sprintf( __( 'Add %s', 'interactions' ), __( 'class', 'interactions' ) ) ],
+ // Translators: %s is the word 'class'.
+ [ 'value' => 'remove', 'label' => sprintf( __( 'Remove %s', 'interactions' ), __( 'class', 'interactions' ) ) ],
+ // Translators: %s is the word 'class'.
+ [ 'value' => 'toggle', 'label' => sprintf( __( 'Toggle %s', 'interactions' ), __( 'class', 'interactions' ) ) ],
+ ]
],
];
@@ -50,6 +50,21 @@
$this->has_duration = false;
$this->has_easing = false;
}
+
+ public function sanitize_data_for_saving( $value ) {
+ if ( is_array( $value ) && isset( $value['class'] ) ) {
+ $value['class'] = sanitize_html_class( $value['class'] );
+ }
+
+ if ( is_array( $value ) && isset( $value['action'] ) ) {
+ $allowed_actions = [ 'add', 'remove', 'toggle' ];
+ if ( ! in_array( $value['action'], $allowed_actions, true ) ) {
+ $value['action'] = 'add';
+ }
+ }
+
+ return $value;
+ }
}
interact_add_action_type( 'toggleClass', 'Interact_Action_Type_Toggle_Class' );
--- a/interactions/src/action-types/class-action-type-toggle-video.php
+++ b/interactions/src/action-types/class-action-type-toggle-video.php
@@ -54,6 +54,23 @@
$this->has_duration = false;
$this->has_easing = false;
}
+
+ public function sanitize_data_for_saving( $value ) {
+ if ( is_array( $value ) && isset( $value['mode'] ) ) {
+ $allowed_modes = [ 'play', 'pause', 'toggle' ];
+ if ( ! in_array( $value['mode'], $allowed_modes, true ) ) {
+ $value['mode'] = 'play';
+ }
+ }
+ if ( is_array( $value ) && isset( $value['startTime'] ) ) {
+ if ( is_numeric( $value['startTime'] ) ) {
+ $value['startTime'] = $value['startTime'] + 0;
+ } else {
+ $value['startTime'] = null;
+ }
+ }
+ return $value;
+ }
}
interact_add_action_type( 'toggleVideo', 'Interact_Action_Type_Toggle_Video' );
--- a/interactions/src/action-types/class-action-type-update-attribute.php
+++ b/interactions/src/action-types/class-action-type-update-attribute.php
@@ -30,6 +30,7 @@
'name' => 'Attribute name',
'type' => 'text',
'default' => '',
+ 'restrictedNotice' => __( 'Some attribute names and values are disallowed unless you are an administrator with unfiltered_html capability for security reasons.', 'interactions' ),
],
'value' => [
'name' => 'Value',
@@ -57,6 +58,79 @@
$this->has_duration = false;
$this->has_easing = false;
}
+
+ public function is_dangerous_attribute( $attribute_name ) {
+ if ( empty( $attribute_name ) || ! is_string( $attribute_name ) ) {
+ return false;
+ }
+
+ $attribute_name = strtolower( trim( $attribute_name ) );
+
+ // Event handler attributes (onclick, onerror, onload, etc.)
+ if ( preg_match( '/^on[a-z]+/', $attribute_name ) ) {
+ return true;
+ }
+
+ // Attributes that can contain JavaScript URIs or code
+ $dangerous_attributes = [
+ 'href',
+ 'src',
+ 'action',
+ 'formaction',
+ // 'style', // Can contain CSS with expression() or javascript: URIs
+ 'form',
+ 'formmethod',
+ 'formtarget',
+ ];
+
+ return in_array( $attribute_name, $dangerous_attributes, true );
+ }
+
+ public function sanitize_data_for_saving( $value ) {
+ // Sanitize action value: ensure $value is an array and attribute/value are strings.
+ if ( ! is_array( $value ) ) {
+ return new WP_Error(
+ 'invalid_structure',
+ __( 'Value must be an array containing attribute and value keys.', 'interactions' )
+ );
+ }
+
+ // Sanitize attribute name
+ if ( isset( $value['attribute'] ) && is_string( $value['attribute'] ) ) {
+ $value['attribute'] = sanitize_key( $value['attribute'] );
+ }
+
+ // Sanitize value if present, and convert to string.
+ if ( isset( $value['value'] ) ) {
+ $value['value'] = $this->sanitize_style_value( $value['value'] );
+ }
+
+ // Sanitize action field for select option.
+ if ( isset( $value['action'] ) ) {
+ $allowed_actions = [ 'update', 'remove', 'toggle' ];
+ if ( ! in_array( $value['action'], $allowed_actions, true ) ) {
+ $value['action'] = 'update';
+ }
+ }
+
+ if ( current_user_can( 'unfiltered_html' ) ) {
+ return $value;
+ }
+
+ if ( ! empty( $value['attribute'] ) && $this->is_dangerous_attribute( $value['attribute'] ) ) {
+ // Only allow dangerous attributes if user has unfiltered_html capability
+ return new WP_Error(
+ 'invalid_attribute',
+ sprintf(
+ // Translators: %s is the attribute name.
+ __( 'The attribute "%s" requires administrator privileges with unfiltered_html capability to prevent security vulnerabilities.', 'interactions' ),
+ esc_html( $value['attribute'] )
+ )
+ );
+ }
+
+ return $value;
+ }
}
interact_add_action_type( 'updateAttribute', 'Interact_Action_Type_Update_Attribute' );
--- a/interactions/src/action-types/class-action-type-visibility.php
+++ b/interactions/src/action-types/class-action-type-visibility.php
@@ -40,6 +40,16 @@
$this->has_easing = false;
$this->has_dynamic = false;
}
+
+ public function sanitize_data_for_saving( $value ) {
+ if ( is_array( $value ) && isset( $value['visibility'] ) ) {
+ $allowed_visibilities = [ 'toggle', 'hide', 'show' ];
+ if ( ! in_array( $value['visibility'], $allowed_visibilities, true ) ) {
+ $value['visibility'] = 'toggle';
+ }
+ }
+ return $value;
+ }
}
interact_add_action_type( 'visibility', 'Interact_Action_Type_Visibility' );
--- a/interactions/src/class-interaction.php
+++ b/interactions/src/class-interaction.php
@@ -59,13 +59,18 @@
* @return int|WP_Error
*/
public static function update( $interaction_data ) {
+ $sanitized_data = self::secure_interaction_data( $interaction_data );
+ if ( is_wp_error( $sanitized_data ) ) {
+ return $sanitized_data;
+ }
+
$post_arr = [
'ID' => self::get_post_id_from_key( $interaction_data['key'] ),
'post_type' => 'interact-interaction',
'post_name' => $interaction_data['key'],
'post_title' => $interaction_data['title'],
// TODO: emojis do not work somehow.
- 'post_content' => wp_slash( maybe_serialize( self::secure_interaction_data( $interaction_data ) ) ),
+ 'post_content' => wp_slash( maybe_serialize( $sanitized_data ) ),
'post_status' => $interaction_data['active'] ? 'publish' : 'interact-inactive',
];
$result = $post_arr['ID'] === 0 ? wp_insert_post( $post_arr ) : wp_update_post( $post_arr );
@@ -79,6 +84,30 @@
}
/**
+ * Sanitizes the interaction value
+ *
+ * @param mixed $value
+ * @return mixed
+ */
+ public static function sanitize_interaction_value( $value ) {
+ if ( current_user_can( 'unfiltered_html' ) ) {
+ return $value;
+ }
+
+ if ( is_array( $value ) ) {
+ foreach ( $value as $key => $val ) {
+ $value[ $key ] = self::sanitize_interaction_value( $val );
+ }
+ }
+
+ if ( is_string( $value ) ) {
+ $value = wp_kses_post( $value );
+ }
+
+ return $value;
+ }
+
+ /**
* Runs through all interaction data, and if the action-type has a
* $verify_integrity set to true, it will hash and sign the action's
* values.
@@ -92,8 +121,19 @@
$action_type = $action['type'];
$action_config = interact_get_action_type( $action_type );
- $action_value = $action['value'];
+ // Sanitize the action value for saving.
+ $action_value = self::sanitize_interaction_value( $action['value'] );
+ // Sanitize for specific action type.
+ $action_value = $action_config->sanitize_data_for_saving( $action_value );
+
+ // If the action value is a WP_Error, return the error.
+ if ( is_wp_error( $action_value ) ) {
+ return $action_value;
+ }
+
+ $interaction_data['timelines'][ $timeline_index ]['actions'][ $action_index ]['value'] = $action_value;
+
if ( $action_config->verify_integrity ) {
$signature = hash_hmac( 'sha256', wp_json_encode( $action_value ), interact_salt() );
--- a/interactions/src/editor/editor.php
+++ b/interactions/src/editor/editor.php
@@ -76,6 +76,7 @@
'restUrl' => trailingslashit( esc_url_raw( rest_url() ) ), // We need to know how to access the REST API.
'restNonce' => wp_create_nonce( 'wp_rest' ), // This needs to be 'wp_rest' to use the built-in nonce verification.
'srcUrl' => untrailingslashit( plugins_url( '/', INTERACT_FILE ) ),
+ 'currentUserCanUnfilteredHtml' => current_user_can( 'unfiltered_html' ),
) );
wp_localize_script( 'interact-editor', 'interactions', $args );
}