Below is a differential between the unpatched vulnerable code and the patched update, for reference.
--- a/wp-user-frontend/admin/form-builder/views/post-form-settings.php
+++ b/wp-user-frontend/admin/form-builder/views/post-form-settings.php
@@ -341,23 +341,20 @@
$is_pro_preview = ! empty( $field['pro_preview'] ) || ( ! wpuf_is_pro_active() && in_array( $field_key, [ 'notification_edit', 'notification_edit_to', 'notification_edit_subject', 'notification_edit_body' ] ) );
- // replace default value if already saved in DB
- if ( ! empty( $field['name'] ) ) {
- preg_match('/wpuf_settings[(.*?)][(.*?)]/', $field['name'], $matches);
-
- if (isset($matches[1]) && isset($matches[2])) {
- $dynamic_key = $matches[1];
- $temp_key = $matches[2];
- $value = isset( $form_settings[ $dynamic_key ][ $temp_key ] ) ? $form_settings[ $dynamic_key ][ $temp_key ] : $value;
- }
- } else {
- $value = isset( $form_settings[ $field_key ] ) ? $form_settings[ $field_key ] : $value; // checking with isset because saved value can be empty string
+ // Replace default value with the saved value from DB.
+ // When an explicit nested name like wpuf_settings[group][key] is provided, read from the nested path.
+ $resolved_from_nested_name = false;
+ if ( ! empty( $field['name'] ) && preg_match( '/wpuf_settings[(.*?)][(.*?)]/', $field['name'], $matches ) ) {
+ $dynamic_key = $matches[1];
+ $temp_key = $matches[2];
+ $value = isset( $form_settings[ $dynamic_key ][ $temp_key ] ) ? $form_settings[ $dynamic_key ][ $temp_key ] : $value;
+ $resolved_from_nested_name = true;
}
// if the field is a pro fields preview, no need to load fields from db
if ( $is_pro_preview ) {
$value = ! empty( $field['value'] ) ? $field['value'] : $value;
- } else {
+ } elseif ( ! $resolved_from_nested_name ) {
$value = isset( $form_settings[ $field_key ] ) ? $form_settings[ $field_key ] : $value; // checking with isset because saved value can be empty string
}
@@ -418,10 +415,21 @@
<label
for="<?php echo esc_attr( $field_key ); ?>"
class="wpuf-relative wpuf-inline-flex wpuf-items-center wpuf-cursor-pointer wpuf-ml-2">
+ <?php
+ // Companion hidden input ensures the toggle always submits a value, even when unchecked.
+ // Without this, an unchecked checkbox is omitted from form serialization, making "saved off"
+ // indistinguishable from "never saved" on the next render. Mirrors the schedule_form pattern.
+ if ( ! $is_pro_preview ) {
+ ?>
+ <input type="hidden" name="<?php echo esc_attr( $name ); ?>" value="off">
+ <?php
+ }
+ ?>
<input
type="checkbox"
id="<?php echo esc_attr( $field_key ); ?>"
name="<?php echo $is_pro_preview ? '' : esc_attr( $name ); ?>"
+ value="on"
<?php echo esc_attr( checked( $toggle_value, 'on', false ) ); ?>
<?php echo $is_pro_preview ? 'disabled' : ''; ?>
class="wpuf-sr-only wpuf-peer">
@@ -634,9 +642,16 @@
$value = ! empty( $inner_field['default'] ) ? $inner_field['default'] : '';
$value = ! empty( $inner_field['value'] ) ? $inner_field['value'] : $value; // default value
+ $inner_field_name = ! empty( $inner_field['name'] ) ? $inner_field['name'] : 'wpuf_settings[' . $inner_field_key . ']';
+
// if the field is a pro fields preview, no need to load fields from db
if ( empty( $inner_field['pro_preview'] ) ) {
- $value = isset( $form_settings[ $inner_field_key ] ) ? $form_settings[ $inner_field_key ] : $value; // checking with isset because saved value can be empty string
+ // When an explicit nested name like wpuf_settings[group][key] is provided, read from the nested path.
+ if ( ! empty( $inner_field['name'] ) && preg_match( '/wpuf_settings[(.*?)][(.*?)]/', $inner_field['name'], $matches ) ) {
+ $value = isset( $form_settings[ $matches[1] ][ $matches[2] ] ) ? $form_settings[ $matches[1] ][ $matches[2] ] : $value;
+ } else {
+ $value = isset( $form_settings[ $inner_field_key ] ) ? $form_settings[ $inner_field_key ] : $value; // checking with isset because saved value can be empty string
+ }
}
++$index_counter;
@@ -655,7 +670,7 @@
:class="setting_class_names('text')"
class="!wpuf-mt-2"
type="<?php echo esc_attr( $inner_field['type'] ); ?>"
- name="wpuf_settings[<?php echo esc_attr( $inner_field_key ); ?>]"
+ name="<?php echo esc_attr( $inner_field_name ); ?>"
<?php echo ! empty( $inner_field['placeholder'] ) ? 'placeholder="' . esc_attr( $inner_field['placeholder'] ) . '"' : ''; ?>
id="<?php echo esc_attr( $inner_field_key ); ?>"
value="<?php echo esc_attr( $value ); ?>"/>
@@ -668,7 +683,7 @@
:class="setting_class_names('text')"
class="datepicker !wpuf-mt-2"
type="text"
- name="wpuf_settings[<?php echo esc_attr( $inner_field_key ); ?>]"
+ name="<?php echo esc_attr( $inner_field_name ); ?>"
id="<?php echo esc_attr( $inner_field_key ); ?>"
value="<?php echo esc_attr( $value ); ?>"/>
<?php
@@ -679,7 +694,7 @@
?>
<select
id="<?php echo esc_attr( $inner_field_key ); ?>"
- name="wpuf_settings[<?php echo esc_attr( $inner_field_key ); ?>]"
+ name="<?php echo esc_attr( $inner_field_name ); ?>"
data-value="<?php echo esc_attr( $value_str ); ?>"
class="!wpuf-mt-2"
:class="setting_class_names('dropdown')">
--- a/wp-user-frontend/class/subscription.php
+++ b/wp-user-frontend/class/subscription.php
@@ -83,7 +83,22 @@
$gateway = isset( $_POST['gateway'] ) ? sanitize_text_field( wp_unslash( $_POST['gateway'] ) ) : 0;
$request_uri = isset( $_SERVER['REQUEST_URI'] ) ? sanitize_text_field( wp_unslash( $_SERVER['REQUEST_URI'] ) ) : '';
- if ( isset( $nonce ) && ! wp_verify_nonce( $nonce, 'wpuf-sub-cancel' ) ) {
+ if ( empty( $nonce ) ) {
+ return;
+ }
+
+ if ( ! wp_verify_nonce( $nonce, 'wpuf-sub-cancel-' . $user_id ) ) {
+ // Legacy nonce compat for theme-overridden templates; self-cancel only.
+ if ( $user_id !== get_current_user_id() ) {
+ return;
+ }
+
+ if ( ! wp_verify_nonce( $nonce, 'wpuf-sub-cancel' ) ) {
+ return;
+ }
+ }
+
+ if ( $user_id !== get_current_user_id() && ! current_user_can( wpuf_admin_role() ) ) {
return;
}
@@ -898,7 +913,7 @@
<?php echo '<p><i>' . esc_html__( 'To cancel the pack, press the following cancel button', 'wp-user-frontend' ) . '</i></p>'; ?>
<form action="" id="wpuf_cancel_subscription" method="post">
- <?php wp_nonce_field( 'wpuf-sub-cancel' ); ?>
+ <?php wp_nonce_field( 'wpuf-sub-cancel-' . get_current_user_id() ); ?>
<input type="hidden" name="user_id" value="<?php echo esc_attr( get_current_user_id() ); ?>">
<input type="hidden" name="gateway" value="<?php echo esc_attr( $payment_gateway ); ?>">
<input type="hidden" name="wpuf_cancel_subscription" value="Cancel">
--- a/wp-user-frontend/includes/Admin/Subscription.php
+++ b/wp-user-frontend/includes/Admin/Subscription.php
@@ -86,7 +86,22 @@
$gateway = isset( $_POST['gateway'] ) ? sanitize_text_field( wp_unslash( $_POST['gateway'] ) ) : 0;
$request_uri = isset( $_SERVER['REQUEST_URI'] ) ? sanitize_text_field( wp_unslash( $_SERVER['REQUEST_URI'] ) ) : '';
- if ( isset( $nonce ) && ! wp_verify_nonce( $nonce, 'wpuf-sub-cancel' ) ) {
+ if ( empty( $nonce ) ) {
+ return false;
+ }
+
+ if ( ! wp_verify_nonce( $nonce, 'wpuf-sub-cancel-' . $user_id ) ) {
+ // Legacy nonce compat for theme-overridden templates; self-cancel only.
+ if ( $user_id !== get_current_user_id() ) {
+ return false;
+ }
+
+ if ( ! wp_verify_nonce( $nonce, 'wpuf-sub-cancel' ) ) {
+ return false;
+ }
+ }
+
+ if ( $user_id !== get_current_user_id() && ! current_user_can( wpuf_admin_role() ) ) {
return false;
}
@@ -937,7 +952,7 @@
<?php echo '<p><i>' . esc_html__( 'To cancel the pack, press the following cancel button', 'wp-user-frontend' ) . '</i></p>'; ?>
<form action="" id="wpuf_cancel_subscription" method="post">
- <?php wp_nonce_field( 'wpuf-sub-cancel' ); ?>
+ <?php wp_nonce_field( 'wpuf-sub-cancel-' . get_current_user_id() ); ?>
<input type="hidden" name="user_id" value="<?php echo esc_attr( get_current_user_id() ); ?>">
<input type="hidden" name="gateway" value="<?php echo esc_attr( $payment_gateway ); ?>">
<input type="hidden" name="wpuf_cancel_subscription" value="Cancel">
--- a/wp-user-frontend/includes/Ajax/Frontend_Form_Ajax.php
+++ b/wp-user-frontend/includes/Ajax/Frontend_Form_Ajax.php
@@ -347,12 +347,12 @@
// Handle Events Calendar integration or standard post creation
$post_id = null;
-
+
// Check if this is an Events Calendar event
if ( isset( $postarr['post_type'] ) && $this->is_events_calendar_post_type( $postarr['post_type'] ) ) {
$post_id = $this->handle_tribe_events_submission( $postarr, $meta_vars, $form_id );
}
-
+
// Use standard post creation if no post_id was created or not an event
if ( ! $post_id ) {
$post_id = wp_insert_post( $postarr );
@@ -596,35 +596,35 @@
*/
private function handle_tribe_events_submission( $postarr, $meta_vars, $form_id ) {
$post_id = null;
-
+
// Try Pro integration handler first if available
if ( wpuf_is_pro_active() && wpuf_pro() && wpuf_pro()->integrations ) {
$integration = wpuf_pro()->integrations->tribe__events__main ?? null;
-
+
if ( $integration && isset( $integration->event_handler ) ) {
$event_handler = $integration->event_handler;
-
+
// Validate that handle_event_submission method exists and is callable
if ( is_callable( [ $event_handler, 'handle_event_submission' ] ) ) {
$post_id = $event_handler->handle_event_submission( $postarr, $meta_vars, $form_id, $this->form_settings );
}
}
}
-
+
// Fallback to free integration handler if Pro handler failed or unavailable
if ( ! $post_id && wpuf() && wpuf()->integrations ) {
$integration = wpuf()->integrations->tribe__events__main ?? null;
-
+
if ( $integration && isset( $integration->event_handler ) ) {
$event_handler = $integration->event_handler;
-
+
// Validate that handle_event_submission method exists and is callable
if ( is_callable( [ $event_handler, 'handle_event_submission' ] ) ) {
$post_id = $event_handler->handle_event_submission( $postarr, $meta_vars, $form_id, $this->form_settings );
}
}
}
-
+
return $post_id;
}
@@ -638,7 +638,7 @@
if ( class_exists( 'WeDevsWpufIntegrationsEvents_CalendarUtilsTEC_Constants' ) ) {
return in_array( $post_type, WeDevsWpufIntegrationsEvents_CalendarUtilsTEC_Constants::TEC_POST_TYPES, true );
}
-
+
// Fallback for backward compatibility
return 'tribe_events' === $post_type;
}
@@ -812,35 +812,20 @@
$post_expiration_message = $user_subscription->get_subscription_exp_msg( $user_wpuf_subscription_pack['pack_id'] );
update_post_meta( $post_id, $this->post_expiration_message, $post_expiration_message );
}
- } elseif ( ! empty( $user_wpuf_subscription_pack ) && isset( $user_wpuf_subscription_pack['expire'] ) && strtotime( $user_wpuf_subscription_pack['expire'] ) <= time() ) {
- if ( isset( $form_settings['expiration_settings']['enable_post_expiration'] ) ) {
- $expire_date = gmdate( 'Y-m-d', strtotime( '+' . $form_settings['expiration_settings']['expiration_time_value'] . ' ' . $form_settings['expiration_settings']['expiration_time_type'] . '' ) );
-
- update_post_meta( $post_id, $this->post_expiration_date, $expire_date );
- // save post status after expiration
- $expired_post_status = $form_settings['expiration_settings']['expired_post_status'];
- update_post_meta( $post_id, $this->expired_post_status, $expired_post_status );
- // if mail active
- if ( isset( $form_settings['expiration_settings']['enable_mail_after_expired'] ) && $form_settings['expiration_settings']['enable_mail_after_expired'] === 'on' ) {
- $post_expiration_message = $form_settings['expiration_settings']['post_expiration_message'];
- update_post_meta( $post_id, $this->post_expiration_message, $post_expiration_message );
- }
- }
- } elseif ( empty( $user_wpuf_subscription_pack ) || $user_wpuf_subscription_pack === 'Cancel' || $user_wpuf_subscription_pack === 'cancel' ) {
- if ( isset( $form_settings['expiration_settings']['enable_post_expiration'] ) ) {
- $expire_date = gmdate( 'Y-m-d', strtotime( '+' . $form_settings['expiration_settings']['expiration_time_value'] . ' ' . $form_settings['expiration_settings']['expiration_time_type'] . '' ) );
- update_post_meta( $post_id, $this->post_expiration_date, $expire_date );
- // save post status after expiration
- $expired_post_status = $form_settings['expiration_settings']['expired_post_status'];
- update_post_meta( $post_id, $this->expired_post_status, $expired_post_status );
- // if mail active
- if ( isset( $form_settings['expiration_settings']['enable_mail_after_expired'] ) && $form_settings['expiration_settings']['enable_mail_after_expired'] === 'on' ) {
- $post_expiration_message = $form_settings['expiration_settings']['post_expiration_message'];
- update_post_meta( $post_id, $this->post_expiration_message, $post_expiration_message );
- }
- }
}
+ /**
+ * Fires after WPUF free has evaluated the subscription-pack branch of
+ * post-expiration, so Pro can write form-driven expiration metadata.
+ *
+ * @since 4.3.3
+ *
+ * @param array $form_settings Form settings array.
+ * @param int $post_id Newly created/updated post ID.
+ * @param array|string $user_wpuf_subscription_pack Current user's subscription pack meta, or empty/'Cancel'.
+ */
+ do_action( 'wpuf_after_post_submit_expiration_settings', $form_settings, $post_id, $user_wpuf_subscription_pack );
+
//Handle featured item when edit
$sub_meta = $user_subscription->handle_featured_item( $post_id, $user_wpuf_subscription_pack );
$user_subscription->update_meta( $sub_meta );
--- a/wp-user-frontend/templates/dashboard/subscription.php
+++ b/wp-user-frontend/templates/dashboard/subscription.php
@@ -91,7 +91,7 @@
<p><i><?php esc_html_e( 'To cancel the pack, press the following cancel button.', 'wp-user-frontend' ); ?></i></p>
<form action="" method="post" style="text-align: center;">
- <?php wp_nonce_field( 'wpuf-sub-cancel' ); ?>
+ <?php wp_nonce_field( 'wpuf-sub-cancel-' . get_current_user_id() ); ?>
<input type="hidden" name="gateway" value="<?php echo esc_attr( $subscription_data['payment_gateway'] ); ?>">
<input type="hidden" name="user_id" value="<?php echo esc_attr( get_current_user_id() ); ?>">
<input type="submit" name="wpuf_cancel_subscription" class="btn btn-sm btn-danger" value="<?php esc_html_e( 'Cancel', 'wp-user-frontend' ); ?>">
@@ -469,7 +469,7 @@
<div class="wpuf-cancel-subscription-section">
<p class="wpuf-cancel-text"><?php esc_html_e( 'To cancel the pack, press the following cancel button.', 'wp-user-frontend' ); ?></p>
<form action="" method="post" class="wpuf-cancel-form">
- <?php wp_nonce_field( 'wpuf-sub-cancel' ); ?>
+ <?php wp_nonce_field( 'wpuf-sub-cancel-' . get_current_user_id() ); ?>
<input type="hidden" name="gateway" value="<?php echo esc_attr( $subscription_data['payment_gateway'] ); ?>">
<input type="hidden" name="user_id" value="<?php echo esc_attr( get_current_user_id() ); ?>">
<button type="submit" name="wpuf_cancel_subscription" class="wpuf-cancel-btn">
--- a/wp-user-frontend/vendor/autoload.php
+++ b/wp-user-frontend/vendor/autoload.php
@@ -4,4 +4,4 @@
require_once __DIR__ . '/composer/autoload_real.php';
-return ComposerAutoloaderInitff0c7435e0c32b4410ff4faeacd1fe87::getLoader();
+return ComposerAutoloaderInitf52cceb826d2463c2ac917b1fce61e2d::getLoader();
--- a/wp-user-frontend/vendor/composer/autoload_real.php
+++ b/wp-user-frontend/vendor/composer/autoload_real.php
@@ -2,7 +2,7 @@
// autoload_real.php @generated by Composer
-class ComposerAutoloaderInitff0c7435e0c32b4410ff4faeacd1fe87
+class ComposerAutoloaderInitf52cceb826d2463c2ac917b1fce61e2d
{
private static $loader;
@@ -24,15 +24,15 @@
require __DIR__ . '/platform_check.php';
- spl_autoload_register(array('ComposerAutoloaderInitff0c7435e0c32b4410ff4faeacd1fe87', 'loadClassLoader'), true, true);
+ spl_autoload_register(array('ComposerAutoloaderInitf52cceb826d2463c2ac917b1fce61e2d', 'loadClassLoader'), true, true);
self::$loader = $loader = new ComposerAutoloadClassLoader(dirname(dirname(__FILE__)));
- spl_autoload_unregister(array('ComposerAutoloaderInitff0c7435e0c32b4410ff4faeacd1fe87', 'loadClassLoader'));
+ spl_autoload_unregister(array('ComposerAutoloaderInitf52cceb826d2463c2ac917b1fce61e2d', 'loadClassLoader'));
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
if ($useStaticLoader) {
require __DIR__ . '/autoload_static.php';
- call_user_func(ComposerAutoloadComposerStaticInitff0c7435e0c32b4410ff4faeacd1fe87::getInitializer($loader));
+ call_user_func(ComposerAutoloadComposerStaticInitf52cceb826d2463c2ac917b1fce61e2d::getInitializer($loader));
} else {
$map = require __DIR__ . '/autoload_namespaces.php';
foreach ($map as $namespace => $path) {
--- a/wp-user-frontend/vendor/composer/autoload_static.php
+++ b/wp-user-frontend/vendor/composer/autoload_static.php
@@ -4,7 +4,7 @@
namespace ComposerAutoload;
-class ComposerStaticInitff0c7435e0c32b4410ff4faeacd1fe87
+class ComposerStaticInitf52cceb826d2463c2ac917b1fce61e2d
{
public static $prefixLengthsPsr4 = array (
'W' =>
@@ -291,9 +291,9 @@
public static function getInitializer(ClassLoader $loader)
{
return Closure::bind(function () use ($loader) {
- $loader->prefixLengthsPsr4 = ComposerStaticInitff0c7435e0c32b4410ff4faeacd1fe87::$prefixLengthsPsr4;
- $loader->prefixDirsPsr4 = ComposerStaticInitff0c7435e0c32b4410ff4faeacd1fe87::$prefixDirsPsr4;
- $loader->classMap = ComposerStaticInitff0c7435e0c32b4410ff4faeacd1fe87::$classMap;
+ $loader->prefixLengthsPsr4 = ComposerStaticInitf52cceb826d2463c2ac917b1fce61e2d::$prefixLengthsPsr4;
+ $loader->prefixDirsPsr4 = ComposerStaticInitf52cceb826d2463c2ac917b1fce61e2d::$prefixDirsPsr4;
+ $loader->classMap = ComposerStaticInitf52cceb826d2463c2ac917b1fce61e2d::$classMap;
}, null, ClassLoader::class);
}
--- a/wp-user-frontend/wpuf.php
+++ b/wp-user-frontend/wpuf.php
@@ -4,7 +4,7 @@
Plugin URI: https://wordpress.org/plugins/wp-user-frontend/
Description: Create, edit, delete, manages your post, pages or custom post types from frontend. Create registration forms, frontend profile and more...
Author: weDevs
-Version: 4.3.2
+Version: 4.3.3
Author URI: https://wedevs.com/?utm_source=WPUF_Author_URI
License: GPL2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html
@@ -23,7 +23,7 @@
require_once $autoload;
}
-define( 'WPUF_VERSION', '4.3.2' );
+define( 'WPUF_VERSION', '4.3.3' );
define( 'WPUF_FILE', __FILE__ );
define( 'WPUF_ROOT', __DIR__ );
define( 'WPUF_ROOT_URI', plugins_url( '', __FILE__ ) );