--- a/wpgsi/admin/class-wpgsi-admin.php
+++ b/wpgsi/admin/class-wpgsi-admin.php
@@ -766,6 +766,7 @@
public function wpgsi_changeIntegrationStatus() {
#
if ( function_exists( 'current_user_can' ) && current_user_can( 'administrator' ) && current_user_can( 'publish_posts' ) && current_user_can( 'publish_pages' ) && current_user_can( 'edit_posts' ) && current_user_can( 'edit_others_posts' ) ) {
+ check_ajax_referer( 'wpgsi_ajax_nonce', 'wpgsi_nonce' );
# Checking SpreadsheetID is set or not
if ( !isset( $_POST['integrationID'] ) or !is_numeric( $_POST['integrationID'] ) ) {
$this->common->wpgsi_log(
@@ -823,6 +824,7 @@
public function wpgsi_changeRemoteUpdateStatus( $id = '' ) {
#
if ( function_exists( 'current_user_can' ) && current_user_can( 'administrator' ) && current_user_can( 'publish_posts' ) && current_user_can( 'publish_pages' ) && current_user_can( 'edit_posts' ) && current_user_can( 'edit_others_posts' ) ) {
+ check_ajax_referer( 'wpgsi_ajax_nonce', 'wpgsi_nonce' );
# Checking SpreadsheetID is set or not
if ( !isset( $_POST['integrationID'] ) or !is_numeric( $_POST['integrationID'] ) ) {
$this->common->wpgsi_log(
@@ -899,6 +901,7 @@
*/
public function wpgsi_createSheetColumnTitles() {
if ( function_exists( 'current_user_can' ) && current_user_can( 'administrator' ) && current_user_can( 'publish_posts' ) && current_user_can( 'publish_pages' ) && current_user_can( 'edit_posts' ) && current_user_can( 'edit_others_posts' ) ) {
+ check_ajax_referer( 'wpgsi_ajax_nonce', 'wpgsi_nonce' );
# Checking SpreadsheetID is set or not
if ( !isset( $_POST['integrationID'], $_POST['eventsAndTitles'] ) or !is_numeric( $_POST['integrationID'] ) ) {
$this->common->wpgsi_log(
@@ -1059,7 +1062,10 @@
# User Email
$userBase64TokenArr['email'] = $current_user->data->user_email;
# Creating token;
- $userToken = base64_encode( json_encode( $userBase64TokenArr ) );
+ # Fix: Base64 encode the payload to prevent dots in JSON interfering with structural dot separator
+ $payload = base64_encode( json_encode( $userBase64TokenArr ) );
+ $signature = hash_hmac( 'sha256', $payload, wp_salt( 'auth' ) );
+ $userToken = base64_encode( $payload . '.' . $signature );
# Check and Balance.
if ( !empty( $userToken ) ) {
$sheetData = @json_decode( $Integrations->post_excerpt, TRUE );
@@ -1121,6 +1127,15 @@
*/
public function wpgsi_delete_connection( $id = '' ) {
if ( function_exists( 'current_user_can' ) && current_user_can( 'administrator' ) && current_user_can( 'publish_posts' ) && current_user_can( 'publish_pages' ) && current_user_can( 'edit_posts' ) && current_user_can( 'edit_others_posts' ) ) {
+ if ( !isset( $_REQUEST['_wpnonce'] ) || !wp_verify_nonce( $_REQUEST['_wpnonce'], 'wpgsi_delete_relation_nonce' ) ) {
+ $this->common->wpgsi_log(
+ get_class( $this ),
+ __METHOD__,
+ "403",
+ "ERROR : Security check failed (nonce)."
+ );
+ wp_die( 'Security check failed' );
+ }
# insert log
$this->common->wpgsi_log(
get_class( $this ),
@@ -1168,6 +1183,15 @@
#
exit;
}
+ if ( !isset( $_POST['wpgsi_nonce'] ) || !wp_verify_nonce( $_POST['wpgsi_nonce'], 'wpgsi_save_integration_action' ) ) {
+ $this->common->wpgsi_log(
+ get_class( $this ),
+ __METHOD__,
+ "403",
+ "ERROR : Security check failed."
+ );
+ wp_die( 'Security check failed' );
+ }
# Setting ERROR status
$errorStatus = TRUE;
//
--- a/wpgsi/admin/class-wpgsi-settings.php
+++ b/wpgsi/admin/class-wpgsi-settings.php
@@ -119,13 +119,14 @@
# Routing Starts
# if it is log then User Will Go this True side, to see the log
if($action == 'log'){
+ $logNonce = wp_create_nonce('wpgsi_log_status_nonce');
# For Log Page
echo"<div class='wrap'>";
echo"<h1 class='wp-heading-inline'> Log Page ";
if(! $logStatusOption OR $logStatusOption == 'enable'){
- echo"<span onclick='window.location="admin.php?page=wpgsi-settings&action=logStatus"' ><code>Log status <input type='checkbox' checked=checked ></code></span> ";
+ echo"<span onclick='window.location="admin.php?page=wpgsi-settings&action=logStatus&_wpnonce=". $logNonce .""' ><code>Log status <input type='checkbox' checked=checked ></code></span> ";
} else {
- echo"<span style='color:red;' onclick='window.location="admin.php?page=wpgsi-settings&action=logStatus"' ><code>Log status <input type='checkbox' ></code></span> ";
+ echo"<span style='color:red;' onclick='window.location="admin.php?page=wpgsi-settings&action=logStatus&_wpnonce=". $logNonce .""' ><code>Log status <input type='checkbox' ></code></span> ";
}
echo"<code>Last 200 log</code> ";
@@ -160,6 +161,10 @@
# for service-account-help slug !
require_once plugin_dir_path(dirname(__FILE__)).'admin/partials/wpgsi-service-ac-help-display.php';
} elseif ( $action == 'logStatus' ){
+ if ( ! isset( $_REQUEST['_wpnonce'] ) || ! wp_verify_nonce( $_REQUEST['_wpnonce'], 'wpgsi_log_status_nonce' ) ) {
+ $this->common->wpgsi_log(get_class($this), __METHOD__,"403", "ERROR : Security check failed (nonce).");
+ wp_die( 'Security check failed' );
+ }
#
if(! $logStatusOption OR $logStatusOption == 'enable'){
# disabling the log
--- a/wpgsi/admin/class-wpgsi-update.php
+++ b/wpgsi/admin/class-wpgsi-update.php
@@ -96,17 +96,86 @@
register_rest_route( 'wpgsi', '/accept', array(
'methods' => 'POST',
'callback' => array($this, 'wpgsi_callBackFuncAccept'),
- 'permission_callback' => '__return_true',
+ 'permission_callback' => array($this, 'wpgsi_permission_check'),
+ 'args' => array(
+ 'token' => array(
+ 'required' => true,
+ 'type' => 'string',
+ ),
+ ),
) );
# For updating data site data
register_rest_route( 'wpgsi', '/update', array(
'methods' => 'GET',
'callback' => array($this, 'wpgsi_callBackFuncUpdate'),
- 'permission_callback' => '__return_true',
+ 'permission_callback' => array($this, 'wpgsi_permission_check'),
+ 'args' => array(
+ 'token' => array(
+ 'required' => true,
+ 'type' => 'string',
+ ),
+ ),
) );
}
/**
+ * Permission callback for REST routes
+ */
+ public function wpgsi_permission_check( $request ) {
+ $token = $request->get_param( 'token' );
+ // Fallback: Check JSON body explicitly if get_param fails
+ if ( empty( $token ) ) {
+ $json_params = $request->get_json_params();
+ if ( !empty( $json_params ) && isset( $json_params['token'] ) ) {
+ $token = $json_params['token'];
+ }
+ }
+ if ( empty( $token ) ) {
+ // Try getting from headers if not in params - just in case
+ $token = $request->get_header( 'x-wpgsi-token' );
+ if ( empty( $token ) ) {
+ $this->common->wpgsi_log(
+ get_class( $this ),
+ __METHOD__,
+ "401",
+ "ERROR: Token not provided in request params (param/json/header)."
+ );
+ return new WP_Error('rest_forbidden', 'Token missing from request', array(
+ 'status' => 401,
+ ));
+ }
+ }
+ $decoded = base64_decode( $token );
+ if ( false === $decoded || strpos( $decoded, '.' ) === false ) {
+ $this->common->wpgsi_log(
+ get_class( $this ),
+ __METHOD__,
+ "401",
+ "ERROR: Token decode failed or format invalid."
+ );
+ return new WP_Error('rest_forbidden', 'Invalid token format', array(
+ 'status' => 401,
+ ));
+ }
+ // Update the wpgsi_permission_check to match the new format
+ list( $payload, $signature ) = explode( '.', $decoded, 2 );
+ $expected_signature = hash_hmac( 'sha256', $payload, wp_salt( 'auth' ) );
+ # NOTE: $payload is now Base64(JSON). This fixes the "dot in JSON" bug.
+ if ( hash_equals( $expected_signature, $signature ) ) {
+ return true;
+ }
+ $this->common->wpgsi_log(
+ get_class( $this ),
+ __METHOD__,
+ "401",
+ "ERROR: Token signature mismatch. Payload: " . $payload
+ );
+ return new WP_Error('rest_forbidden', 'Signature Mismatch.', array(
+ 'status' => 401,
+ ));
+ }
+
+ /**
* This is the callback function of register_rest_route() Function
* This Function get the Request data & handel the Request and return the response
* *** IMPORTANT if you use *** POST MAN *** mast use data as JSON ***
@@ -134,7 +203,15 @@
return $response;
}
# converting data from base64 string
- $jsonString = @base64_decode( $data['token'] );
+ $decoded = base64_decode( $data['token'] );
+ if ( strpos( $decoded, '.' ) !== false ) {
+ list( $b64Payload, $signature ) = explode( '.', $decoded, 2 );
+ $jsonString = base64_decode( $b64Payload );
+ // Fix: Decode payload to get JSON
+ } else {
+ $jsonString = "";
+ // Fail
+ }
# encoding JSON string to PHP array
$updateInfo = json_decode( $jsonString, TRUE );
# User information validation; $updateInfo array and isset( ) check for ID, UID, email
@@ -601,6 +678,18 @@
# Setting Update List on the Site Option cache *** important without saving it will n
update_option( 'wpgsi_remote_data', $processedData );
update_option( 'wpgsi_integrationID', $Integration->ID );
+ # Fix: Save original status to restore it correctly after update
+ # Save current status if original status hasn't been saved yet for this update cycle.
+ $existing_original_status = get_option( 'wpgsi_integration_original_status' );
+ if ( empty( $existing_original_status ) ) {
+ update_option( 'wpgsi_integration_original_status', $Integration->post_status );
+ } else {
+ # If we already have a status saved, and the current status is publish, update it.
+ # This handles the case where a previous run crashed but the user re-enabled the integration manually.
+ if ( $Integration->post_status == 'publish' ) {
+ update_option( 'wpgsi_integration_original_status', 'publish' );
+ }
+ }
# After Update to the Array Unset The Variable For Memory management || clear the Memory
unset($data);
unset($updateInfo);
@@ -657,7 +746,12 @@
# getting the Integration.
$post = get_post( $integration_id );
# if Post is Publish, Stop the Post by making it Pending.
+ # Only do this if we haven't already saved the status for this update cycle.
if ( $post->post_status == 'publish' ) {
+ # If we are here, it means we are catching an integration that is still published.
+ # This could be the FIRST batch of an update.
+ # We should ensure we saved its state.
+ update_option( 'wpgsi_integration_original_status', 'publish' );
$update_post = array(
'ID' => $integration_id,
'post_status' => 'pending',
@@ -707,14 +801,20 @@
if ( empty( $savedData ) ) {
# getting integration ID
$post = get_post( $integration_id );
- # if integration is Pending Publish the integration
- if ( $post->post_status == 'pending' ) {
+ # Restore original status logic
+ $original_status = get_option( 'wpgsi_integration_original_status' );
+ # Only re-enable if it was originally 'publish'
+ if ( $original_status === 'publish' ) {
+ # Logic: Always try to restore to publish if original was publish,
+ # regardless of current status, to ensure consistency.
$update_post = array(
'ID' => $integration_id,
'post_status' => 'publish',
);
wp_update_post( $update_post, true );
}
+ # Clean up original status option
+ delete_option( 'wpgsi_integration_original_status' );
# Delete Product cache Too || no garbage
delete_option( 'wpgsi_remote_data' );
# Delete wpgsi_integrationID
--- a/wpgsi/admin/partials/wpgsi-edit-integration-display.php
+++ b/wpgsi/admin/partials/wpgsi-edit-integration-display.php
@@ -11,6 +11,7 @@
<!-- <pre> {{ $data }} </pre> -->
<br>
<form action="<?php echo esc_url(admin_url('admin-post.php'));?>" method="post">
+ <?php wp_nonce_field( 'wpgsi_save_integration_action', 'wpgsi_nonce' ); ?>
<input type="hidden" name="action" value="wpgsi_Integration">
<input type="hidden" name="status" value="edit_Integration" />
<input type="hidden" name="ID" value= "<?php echo esc_attr($_GET["id"]);?>"/>
--- a/wpgsi/admin/partials/wpgsi-new-integration-display.php
+++ b/wpgsi/admin/partials/wpgsi-new-integration-display.php
@@ -12,6 +12,7 @@
<!-- <pre> {{ $data }} </pre> -->
<br>
<form action="<?php echo esc_url(admin_url('admin-post.php'));?>" method="post">
+ <?php wp_nonce_field( 'wpgsi_save_integration_action', 'wpgsi_nonce' ); ?>
<input type="hidden" name="action" value="wpgsi_Integration">
<input type="hidden" name="status" value="new_Integration">
<input type="hidden" name="DataSource" v-model="DataSource">
--- a/wpgsi/admin/partials/wpgsi-remoteUpdate.php
+++ b/wpgsi/admin/partials/wpgsi-remoteUpdate.php
@@ -74,7 +74,7 @@
console.log("SUCCESS: Site successfully saved the data to the Option table.");
// request for update loop starts
for(let i = 1; i < 10; i++){
- var updateResponse = UrlFetchApp.fetch("<?php echo get_site_url() . '/wp-json/wpgsi/update'?>");
+ var updateResponse = UrlFetchApp.fetch("<?php echo get_site_url() . '/wp-json/wpgsi/update' . '?token=' . $userToken ?>");
var updateResponseJSON = JSON.parse(updateResponse.getContentText());
// Breaking the update request Loop if Update successfully completed
if(updateResponseJSON['code'] && updateResponseJSON['code'] == 202){
@@ -173,7 +173,6 @@
</p>
</div>
-
<div id='step_4'>
<br><br>
<h3> <span style='color:red;'> Step 3 : </span> Tips, Tricks & Safety measures. </h3>
--- a/wpgsi/includes/class-wpgsi-list-table.php
+++ b/wpgsi/includes/class-wpgsi-list-table.php
@@ -440,7 +440,8 @@
// AJAX Data
var data = {
"action" : 'wpgsi_changeIntegrationStatus',
- "integrationID" : integrationID
+ "integrationID" : integrationID,
+ "wpgsi_nonce" : "<?php echo wp_create_nonce('wpgsi_ajax_nonce'); ?>"
};
// Request Object
let request = new XMLHttpRequest();
@@ -468,6 +469,7 @@
"action" : 'wpgsi_createSheetColumnTitles',
"integrationID" : integrationID,
"eventsAndTitles" : eventsAndTitles,
+ "wpgsi_nonce" : "<?php echo wp_create_nonce('wpgsi_ajax_nonce'); ?>"
};
// Request Object
let request = new XMLHttpRequest();
@@ -493,7 +495,8 @@
// AJAX Data
var data = {
"action" : 'wpgsi_changeRemoteUpdateStatus',
- "integrationID" : integrationID
+ "integrationID" : integrationID,
+ "wpgsi_nonce" : "<?php echo wp_create_nonce('wpgsi_ajax_nonce'); ?>"
};
// Request Object
let request = new XMLHttpRequest();
--- a/wpgsi/includes/class-wpgsi.php
+++ b/wpgsi/includes/class-wpgsi.php
@@ -46,7 +46,7 @@
if(defined('WPGSI_VERSION')){
$this->version = WPGSI_VERSION;
} else {
- $this->version = '3.8.3';
+ $this->version = '3.8.4';
}
$this->plugin_name = 'wpgsi';
--- a/wpgsi/includes/freemius/includes/class-freemius.php
+++ b/wpgsi/includes/freemius/includes/class-freemius.php
@@ -3629,7 +3629,7 @@
$this->delete_current_install( false );
- $license_key = false;
+ $license = null;
if (
is_object( $this->_license ) &&
@@ -3637,20 +3637,21 @@
( WP_FS__IS_LOCALHOST_FOR_SERVER || FS_Site::is_localhost_by_address( self::get_unfiltered_site_url() ) )
)
) {
- $license_key = $this->_license->secret_key;
+ $license = $this->_license;
}
return $this->opt_in(
false,
false,
false,
- $license_key,
+ ( is_object( $license ) ? $license->secret_key : false ),
false,
false,
false,
null,
array(),
- false
+ false,
+ ( is_object( $license ) ? $license->user_id : null )
);
}
@@ -4494,33 +4495,31 @@
return;
}
- if ( $this->has_api_connectivity() ) {
- if ( self::is_cron() ) {
- $this->hook_callback_to_sync_cron();
- } else if ( $this->is_user_in_admin() ) {
- /**
- * Schedule daily data sync cron if:
- *
- * 1. User opted-in (for tracking).
- * 2. If skipped, but later upgraded (opted-in via upgrade).
- *
- * @author Vova Feldman (@svovaf)
- * @since 1.1.7.3
- *
- */
- if ( $this->is_registered() && $this->is_tracking_allowed() ) {
- $this->maybe_schedule_sync_cron();
- }
+ $this->hook_callback_to_sync_cron();
- /**
- * Check if requested for manual blocking background sync.
- */
- if ( fs_request_has( 'background_sync' ) ) {
- self::require_pluggable_essentials();
- self::wp_cookie_constants();
+ if ( $this->has_api_connectivity() && ! self::is_cron() && $this->is_user_in_admin() ) {
+ /**
+ * Schedule daily data sync cron if:
+ *
+ * 1. User opted-in (for tracking).
+ * 2. If skipped, but later upgraded (opted-in via upgrade).
+ *
+ * @author Vova Feldman (@svovaf)
+ * @since 1.1.7.3
+ *
+ */
+ if ( $this->is_registered() && $this->is_tracking_allowed() ) {
+ $this->maybe_schedule_sync_cron();
+ }
- $this->run_manual_sync();
- }
+ /**
+ * Check if requested for manual blocking background sync.
+ */
+ if ( fs_request_has( 'background_sync' ) ) {
+ self::require_pluggable_essentials();
+ self::wp_cookie_constants();
+
+ $this->run_manual_sync();
}
}
@@ -7659,7 +7658,14 @@
$parent_fs->get_current_or_network_user()->email,
false,
false,
- $license->secret_key
+ $license->secret_key,
+ false,
+ false,
+ false,
+ null,
+ array(),
+ true,
+ $license->user_id
);
} else {
// Activate the license.
@@ -7723,7 +7729,9 @@
false,
false,
null,
- $sites
+ $sites,
+ true,
+ $license->user_id
);
} else {
$blog_2_install_map = array();
@@ -7777,7 +7785,7 @@
* @param array $sites
* @param int $blog_id
*/
- private function maybe_activate_bundle_license( FS_Plugin_License $license = null, $sites = array(), $blog_id = 0 ) {
+ private function maybe_activate_bundle_license( $license = null, $sites = array(), $blog_id = 0 ) {
if ( ! is_object( $license ) && $this->has_active_valid_license() ) {
$license = $this->_license;
}
@@ -7949,7 +7957,8 @@
null,
null,
$sites,
- ( $current_blog_id > 0 ? $current_blog_id : null )
+ ( $current_blog_id > 0 ? $current_blog_id : null ),
+ $license->user_id
);
}
}
@@ -8830,8 +8839,13 @@
isset( $site_active_plugins[ $basename ] )
) {
// Plugin was site level activated.
- $site_active_plugins_cache->plugins[ $basename ] = $network_plugins[ $basename ];
- $site_active_plugins_cache->plugins[ $basename ]['is_active'] = true;
+ $site_active_plugins_cache->plugins[ $basename ] = array(
+ 'slug' => $network_plugins[ $basename ]['slug'],
+ 'version' => $network_plugins[ $basename ]['Version'],
+ 'title' => $network_plugins[ $basename ]['Name'],
+ 'is_active' => $is_active,
+ 'is_uninstalled' => false,
+ );
} else if ( isset( $site_active_plugins_cache->plugins[ $basename ] ) &&
! isset( $site_active_plugins[ $basename ] )
) {
@@ -11576,7 +11590,7 @@
continue;
}
- $missing_plan = self::_get_plan_by_id( $plan_id );
+ $missing_plan = self::_get_plan_by_id( $plan_id, false );
if ( is_object( $missing_plan ) ) {
$plans[] = $missing_plan;
@@ -11738,10 +11752,10 @@
*
* @return FS_Plugin_Plan|false
*/
- function _get_plan_by_id( $id ) {
+ function _get_plan_by_id( $id, $allow_sync = true ) {
$this->_logger->entrance();
- if ( ! is_array( $this->_plans ) || 0 === count( $this->_plans ) ) {
+ if ( $allow_sync && ( ! is_array( $this->_plans ) || 0 === count( $this->_plans ) ) ) {
$this->_sync_plans();
}
@@ -12385,7 +12399,7 @@
*
* @param FS_Plugin_License $license
*/
- private function set_license( FS_Plugin_License $license = null ) {
+ private function set_license( $license = null ) {
$this->_license = $license;
$this->maybe_update_whitelabel_flag( $license );
@@ -13485,7 +13499,8 @@
fs_request_get( 'module_id', null, 'post' ),
fs_request_get( 'user_id', null ),
fs_request_get_bool( 'is_extensions_tracking_allowed', null ),
- fs_request_get_bool( 'is_diagnostic_tracking_allowed', null )
+ fs_request_get_bool( 'is_diagnostic_tracking_allowed', null ),
+ fs_request_get( 'license_owner_id', null )
);
if (
@@ -13634,6 +13649,7 @@
* @param null|number $plugin_id
* @param array $sites
* @param int $blog_id
+ * @param null|number $license_owner_id
*
* @return array {
* @var bool $success
@@ -13648,7 +13664,8 @@
$is_marketing_allowed = null,
$plugin_id = null,
$sites = array(),
- $blog_id = null
+ $blog_id = null,
+ $license_owner_id = null
) {
$this->_logger->entrance();
@@ -13659,7 +13676,11 @@
$sites,
$is_marketing_allowed,
$blog_id,
- $plugin_id
+ $plugin_id,
+ null,
+ null,
+ null,
+ $license_owner_id
);
// No need to show the sticky after license activation notice after migrating a license.
@@ -13733,9 +13754,10 @@
* @param null|bool $is_marketing_allowed
* @param null|int $blog_id
* @param null|number $plugin_id
- * @param null|number $license_owner_id
+ * @param null|number $user_id
* @param bool|null $is_extensions_tracking_allowed
* @param bool|null $is_diagnostic_tracking_allowed Since 2.5.0.2 to allow license activation with minimal data footprint.
+ * @param null|number $license_owner_id
*
*
* @return array {
@@ -13750,9 +13772,10 @@
$is_marketing_allowed = null,
$blog_id = null,
$plugin_id = null,
- $license_owner_id = null,
+ $user_id = null,
$is_extensions_tracking_allowed = null,
- $is_diagnostic_tracking_allowed = null
+ $is_diagnostic_tracking_allowed = null,
+ $license_owner_id = null
) {
$this->_logger->entrance();
@@ -13841,10 +13864,10 @@
$install_ids = array();
- $change_owner = FS_User::is_valid_id( $license_owner_id );
+ $change_owner = FS_User::is_valid_id( $user_id );
if ( $change_owner ) {
- $params['user_id'] = $license_owner_id;
+ $params['user_id'] = $user_id;
$installs_info_by_slug_map = $fs->get_parent_and_addons_installs_info();
@@ -13920,7 +13943,9 @@
false,
false,
$is_marketing_allowed,
- $sites
+ $sites,
+ true,
+ $license_owner_id
);
if ( isset( $next_page->error ) ) {
@@ -14009,6 +14034,10 @@
$result['next_page'] = $next_page;
}
+ if ( $result['success'] ) {
+ $this->do_action( 'after_license_activation' );
+ }
+
return $result;
}
@@ -15630,7 +15659,7 @@
*
* @return bool Since 2.3.1 returns if a switch was made.
*/
- function switch_to_blog( $blog_id, FS_Site $install = null, $flush = false ) {
+ function switch_to_blog( $blog_id, $install = null, $flush = false ) {
if ( ! is_numeric( $blog_id ) ) {
return false;
}
@@ -15757,6 +15786,10 @@
function get_site_info( $site = null, $load_registration = false ) {
$this->_logger->entrance();
+ $fs_hook_snapshot = new FS_Hook_Snapshot();
+ // Remove all filters from `switch_blog`.
+ $fs_hook_snapshot->remove( 'switch_blog' );
+
$switched = false;
$registration_date = null;
@@ -15816,6 +15849,9 @@
restore_current_blog();
}
+ // Add the filters back to `switch_blog`.
+ $fs_hook_snapshot->restore( 'switch_blog' );
+
return $info;
}
@@ -16936,14 +16972,13 @@
*
* @param array $override_with
* @param bool|int|null $network_level_or_blog_id If true, return params for network level opt-in. If integer, get params for specified blog in the network.
+ * @param bool $skip_user_info
*
* @return array
*/
- function get_opt_in_params( $override_with = array(), $network_level_or_blog_id = null ) {
+ function get_opt_in_params( $override_with = array(), $network_level_or_blog_id = null, $skip_user_info = false ) {
$this->_logger->entrance();
- $current_user = self::_get_current_wp_user();
-
$activation_action = $this->get_unique_affix() . '_activate_new';
$return_url = $this->is_anonymous() ?
// If skipped already, then return to the account page.
@@ -16954,9 +16989,6 @@
$versions = $this->get_versions();
$params = array_merge( $versions, array(
- 'user_firstname' => $current_user->user_firstname,
- 'user_lastname' => $current_user->user_lastname,
- 'user_email' => $current_user->user_email,
'plugin_slug' => $this->_slug,
'plugin_id' => $this->get_id(),
'plugin_public_key' => $this->get_public_key(),
@@ -16972,6 +17004,21 @@
'is_localhost' => WP_FS__IS_LOCALHOST,
) );
+ if (
+ ! $skip_user_info &&
+ (
+ empty( $override_with['user_firstname'] ) ||
+ empty( $override_with['user_lastname'] ) ||
+ empty( $override_with['user_email'] )
+ )
+ ) {
+ $current_user = self::_get_current_wp_user();
+
+ $params['user_firstname'] = $current_user->user_firstname;
+ $params['user_lastname'] = $current_user->user_lastname;
+ $params['user_email'] = $current_user->user_email;
+ }
+
if ( $this->is_addon() ) {
$parent_fs = $this->get_parent_instance();
@@ -17051,6 +17098,7 @@
* @param null|bool $is_marketing_allowed
* @param array $sites If network-level opt-in, an array of containing details of sites.
* @param bool $redirect
+ * @param null|number $license_owner_id
*
* @return string|object
* @use WP_Error
@@ -17065,15 +17113,11 @@
$is_disconnected = false,
$is_marketing_allowed = null,
$sites = array(),
- $redirect = true
+ $redirect = true,
+ $license_owner_id = null
) {
$this->_logger->entrance();
- if ( false === $email ) {
- $current_user = self::_get_current_wp_user();
- $email = $current_user->user_email;
- }
-
/**
* @since 1.2.1 If activating with license key, ignore the context-user
* since the user will be automatically loaded from the license.
@@ -17083,6 +17127,11 @@
$this->_storage->remove( 'pending_license_key' );
if ( ! $is_uninstall ) {
+ if ( false === $email ) {
+ $current_user = self::_get_current_wp_user();
+ $email = $current_user->user_email;
+ }
+
$fs_user = Freemius::_get_user_by_email( $email );
if ( is_object( $fs_user ) && ! $this->is_pending_activation() ) {
return $this->install_with_user(
@@ -17097,15 +17146,22 @@
}
}
+ $skip_user_info = ( ! empty( $license_key ) && FS_User::is_valid_id( $license_owner_id ) );
+
$user_info = array();
- if ( ! empty( $email ) ) {
- $user_info['user_email'] = $email;
- }
- if ( ! empty( $first ) ) {
- $user_info['user_firstname'] = $first;
- }
- if ( ! empty( $last ) ) {
- $user_info['user_lastname'] = $last;
+
+ if ( ! $skip_user_info ) {
+ if ( ! empty( $email ) ) {
+ $user_info['user_email'] = $email;
+ }
+
+ if ( ! empty( $first ) ) {
+ $user_info['user_firstname'] = $first;
+ }
+
+ if ( ! empty( $last ) ) {
+ $user_info['user_lastname'] = $last;
+ }
}
if ( ! empty( $sites ) ) {
@@ -17116,7 +17172,7 @@
$is_network = false;
}
- $params = $this->get_opt_in_params( $user_info, $is_network );
+ $params = $this->get_opt_in_params( $user_info, $is_network, $skip_user_info );
$filtered_license_key = false;
if ( is_string( $license_key ) ) {
@@ -18112,7 +18168,7 @@
private function _activate_addon_account(
Freemius $parent_fs,
$network_level_or_blog_id = null,
- FS_Plugin_License $bundle_license = null
+ $bundle_license = null
) {
if ( $this->is_registered() ) {
// Already activated.
@@ -18745,7 +18801,7 @@
* @return bool
*/
function is_pricing_page_visible() {
- return (
+ $visible = (
// Has at least one paid plan.
$this->has_paid_plan() &&
// Didn't ask to hide the pricing page.
@@ -18753,6 +18809,8 @@
// Don't have a valid active license or has more than one plan.
( ! $this->is_paying() || ! $this->is_single_plan( true ) )
);
+
+ return $this->apply_filters( 'is_pricing_page_visible', $visible );
}
/**
@@ -19708,7 +19766,7 @@
* @param null|int $network_level_or_blog_id Since 2.0.0
* @param FS_Site $site Since 2.0.0
*/
- private function _store_site( $store = true, $network_level_or_blog_id = null, FS_Site $site = null, $is_backup = false ) {
+ private function _store_site( $store = true, $network_level_or_blog_id = null, $site = null, $is_backup = false ) {
$this->_logger->entrance();
if ( is_null( $site ) ) {
@@ -20561,11 +20619,18 @@
* @param bool $flush Since 1.1.7.3
* @param int $expiration Since 1.2.2.7
* @param bool|string $newer_than Since 2.2.1
+ * @param bool $fetch_upgrade_notice Since 2.12.1
*
* @return object|false New plugin tag info if exist.
*/
- private function _fetch_newer_version( $plugin_id = false, $flush = true, $expiration = WP_FS__TIME_24_HOURS_IN_SEC, $newer_than = false ) {
- $latest_tag = $this->_fetch_latest_version( $plugin_id, $flush, $expiration, $newer_than );
+ private function _fetch_newer_version(
+ $plugin_id = false,
+ $flush = true,
+ $expiration = WP_FS__TIME_24_HOURS_IN_SEC,
+ $newer_than = false,
+ $fetch_upgrade_notice = true
+ ) {
+ $latest_tag = $this->_fetch_latest_version( $plugin_id, $flush, $expiration, $newer_than, false, $fetch_upgrade_notice );
if ( ! is_object( $latest_tag ) ) {
return false;
@@ -20598,19 +20663,18 @@
*
* @param bool|number $plugin_id
* @param bool $flush Since 1.1.7.3
- * @param int $expiration Since 1.2.2.7
- * @param bool|string $newer_than Since 2.2.1
*
* @return bool|FS_Plugin_Tag
*/
- function get_update( $plugin_id = false, $flush = true, $expiration = FS_Plugin_Updater::UPDATES_CHECK_CACHE_EXPIRATION, $newer_than = false ) {
+ function get_update( $plugin_id = false, $flush = true ) {
$this->_logger->entrance();
if ( ! is_numeric( $plugin_id ) ) {
$plugin_id = $this->_plugin->id;
}
- $this->check_updates( true, $plugin_id, $flush, $expiration, $newer_than );
+ $this->check_updates( true, $plugin_id, $flush );
+
$updates = $this->get_all_updates();
return isset( $updates[ $plugin_id ] ) && is_object( $updates[ $plugin_id ] ) ? $updates[ $plugin_id ] : false;
@@ -21548,7 +21612,14 @@
false,
false,
false,
- $premium_license->secret_key
+ $premium_license->secret_key,
+ false,
+ false,
+ false,
+ null,
+ array(),
+ true,
+ $premium_license->user_id
);
return;
@@ -21600,6 +21671,8 @@
return;
}
+ $this->do_action( 'after_license_activation' );
+
$premium_license = new FS_Plugin_License( $license );
// Updated site plan.
@@ -21679,6 +21752,8 @@
'error'
);
+ $this->do_action( 'after_license_deactivation', $license );
+
return;
}
@@ -21699,6 +21774,8 @@
$this->_store_account();
+ $this->do_action( 'after_license_deactivation', $license );
+
if ( $show_notice ) {
$this->_admin_notices->add(
sprintf( $this->is_only_premium() ?
@@ -22060,6 +22137,7 @@
* @param int $expiration Since 1.2.2.7
* @param bool|string $newer_than Since 2.2.1
* @param bool|string $fetch_readme Since 2.2.1
+ * @param bool $fetch_upgrade_notice Since 2.12.1
*
* @return object|false Plugin latest tag info.
*/
@@ -22068,7 +22146,8 @@
$flush = true,
$expiration = WP_FS__TIME_24_HOURS_IN_SEC,
$newer_than = false,
- $fetch_readme = true
+ $fetch_readme = true,
+ $fetch_upgrade_notice = false
) {
$this->_logger->entrance();
@@ -22141,6 +22220,10 @@
$expiration = null;
}
+ if ( true === $fetch_upgrade_notice ) {
+ $latest_version_endpoint = add_query_arg( 'include_upgrade_notice', 'true', $latest_version_endpoint );
+ }
+
$tag = $this->get_api_site_or_plugin_scope()->get(
$latest_version_endpoint,
$flush,
@@ -22286,20 +22369,20 @@
* was initiated by the admin.
* @param bool|number $plugin_id
* @param bool $flush Since 1.1.7.3
- * @param int $expiration Since 1.2.2.7
- * @param bool|string $newer_than Since 2.2.1
*/
- private function check_updates(
- $background = false,
- $plugin_id = false,
- $flush = true,
- $expiration = FS_Plugin_Updater::UPDATES_CHECK_CACHE_EXPIRATION,
- $newer_than = false
- ) {
+ private function check_updates( $background = false, $plugin_id = false, $flush = true ) {
$this->_logger->entrance();
+ $newer_than = ( $this->is_premium() ? $this->get_plugin_version() : false );
+
// Check if there's a newer version for download.
- $new_version = $this->_fetch_newer_version( $plugin_id, $flush, $expiration, $newer_than );
+ $new_version = $this->_fetch_newer_version(
+ $plugin_id,
+ $flush,
+ FS_Plugin_Updater::UPDATES_CHECK_CACHE_EXPIRATION,
+ $newer_than,
+ ( false !== $newer_than )
+ );
$update = null;
if ( is_object( $new_version ) ) {
@@ -23444,7 +23527,7 @@
$params['plugin_public_key'] = $this->get_public_key();
}
- $result = $api->get( 'pricing.json?' . http_build_query( $params ) );
+ $result = $api->get( $this->add_show_pending( 'pricing.json?' . http_build_query( $params ) ) );
break;
case 'start_trial':
$trial_plan_id = fs_request_get( 'plan_id' );
@@ -24625,23 +24708,39 @@
$this->get_premium_slug() :
$this->premium_plugin_basename();
- return sprintf(
- /* translators: %1$s: Product title; %2$s: Plan title */
- $this->get_text_inline( ' The paid version of %1$s is already installed. Please activate it to start benefiting the %2$s features. %3$s', 'activate-premium-version' ),
- sprintf( '<em>%s</em>', esc_html( $this->get_plugin_title() ) ),
- $plan_title,
- sprintf(
- '<a style="margin-left: 10px;" href="%s"><button class="button button-primary">%s</button></a>',
- ( $this->is_theme() ?
- wp_nonce_url( 'themes.php?action=activate&stylesheet=' . $premium_theme_slug_or_plugin_basename, 'switch-theme_' . $premium_theme_slug_or_plugin_basename ) :
- wp_nonce_url( 'plugins.php?action=activate&plugin=' . $premium_theme_slug_or_plugin_basename, 'activate-plugin_' . $premium_theme_slug_or_plugin_basename ) ),
- esc_html( sprintf(
- /* translators: %s: Plan title */
- $this->get_text_inline( 'Activate %s features', 'activate-x-features' ),
- $plan_title
- ) )
- )
- );
+ if ( is_admin() ) {
+ return sprintf(
+ /* translators: %1$s: Product title; %2$s: Plan title */
+ $this->get_text_inline( ' The paid version of %1$s is already installed. Please activate it to start benefiting from the %2$s features. %3$s', 'activate-premium-version' ),
+ sprintf( '<em>%s</em>', esc_html( $this->get_plugin_title() ) ),
+ $plan_title,
+ sprintf(
+ '<a style="margin-left: 10px;" href="%s"><button class="button button-primary">%s</button></a>',
+ ( $this->is_theme() ?
+ wp_nonce_url( 'themes.php?action=activate&stylesheet=' . $premium_theme_slug_or_plugin_basename, 'switch-theme_' . $premium_theme_slug_or_plugin_basename ) :
+ wp_nonce_url( 'plugins.php?action=activate&plugin=' . $premium_theme_slug_or_plugin_basename, 'activate-plugin_' . $premium_theme_slug_or_plugin_basename ) ),
+ esc_html( sprintf(
+ /* translators: %s: Plan title */
+ $this->get_text_inline( 'Activate %s features', 'activate-x-features' ),
+ $plan_title
+ ) )
+ )
+ );
+ } else {
+ return sprintf(
+ /* translators: %1$s: Product title; %3$s: Plan title */
+ $this->get_text_inline( ' The paid version of %1$s is already installed. Please navigate to the %2$s to activate it and start benefiting from the %3$s features.', 'activate-premium-version-plugins-page' ),
+ sprintf( '<em>%s</em>', esc_html( $this->get_plugin_title() ) ),
+ sprintf(
+ '<a href="%s">%s</a>',
+ admin_url( $this->is_theme() ? 'themes.php' : 'plugins.php' ),
+ ( $this->is_theme() ?
+ $this->get_text_inline( 'Themes page', 'themes-page' ) :
+ $this->get_text_inline( 'Plugins page', 'plugins-page' ) )
+ ),
+ $plan_title
+ );
+ }
} else {
// @since 1.2.1.5 The free version is auto deactivated.
$deactivation_step = version_compare( $this->version, '1.2.1.5', '<' ) ?
--- a/wpgsi/includes/freemius/includes/class-fs-hook-snapshot.php
+++ b/wpgsi/includes/freemius/includes/class-fs-hook-snapshot.php
@@ -0,0 +1,45 @@
+<?php
+ /**
+ * @package Freemius
+ * @copyright Copyright (c) 2025, Freemius, Inc.
+ * @license https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License Version 3
+ * @since 2.12.2
+ */
+
+ if ( ! defined( 'ABSPATH' ) ) {
+ exit;
+ }
+
+ /**
+ * Class FS_Hook_Snapshot
+ *
+ * This class allows you to take a snapshot of the current actions attached to a WordPress hook, remove them, and restore them later.
+ */
+ class FS_Hook_Snapshot {
+
+ private $removed_actions = array();
+
+ /**
+ * Remove all actions from a given hook and store them for later restoration.
+ */
+ public function remove( $hook ) {
+ global $wp_filter;
+
+ if ( ! empty( $wp_filter ) && isset( $wp_filter[ $hook ] ) ) {
+ $this->removed_actions[ $hook ] = $wp_filter[ $hook ];
+ unset( $wp_filter[ $hook ] );
+ }
+ }
+
+ /**
+ * Restore previously removed actions for a given hook.
+ */
+ public function restore( $hook ) {
+ global $wp_filter;
+
+ if ( ! empty( $wp_filter ) && isset( $this->removed_actions[ $hook ] ) ) {
+ $wp_filter[ $hook ] = $this->removed_actions[ $hook ];
+ unset( $this->removed_actions[ $hook ] );
+ }
+ }
+ }
No newline at end of file
--- a/wpgsi/includes/freemius/includes/class-fs-logger.php
+++ b/wpgsi/includes/freemius/includes/class-fs-logger.php
@@ -636,7 +636,17 @@
$offset = 0,
$order = false
) {
- global $wpdb;
+ if ( empty( $filename ) ) {
+ $filename = 'fs-logs-' . date( 'Y-m-d_H-i-s', WP_FS__SCRIPT_START_TIME ) . '.csv';
+ }
+
+ $upload_dir = wp_upload_dir();
+ $filepath = rtrim( $upload_dir['path'], '/' ) . "/{$filename}";
+
+ WP_Filesystem();
+ if ( ! $GLOBALS['wp_filesystem']->is_writable( dirname( $filepath ) ) ) {
+ return false;
+ }
$query = self::build_db_logs_query(
$filters,
@@ -646,14 +656,6 @@
true
);
- $upload_dir = wp_upload_dir();
- if ( empty( $filename ) ) {
- $filename = 'fs-logs-' . date( 'Y-m-d_H-i-s', WP_FS__SCRIPT_START_TIME ) . '.csv';
- }
- $filepath = rtrim( $upload_dir['path'], '/' ) . "/{$filename}";
-
- $query .= " INTO OUTFILE '{$filepath}' FIELDS TERMINATED BY 't' ESCAPED BY '\\' OPTIONALLY ENCLOSED BY '"' LINES TERMINATED BY '\n'";
-
$columns = '';
for ( $i = 0, $len = count( self::$_log_columns ); $i < $len; $i ++ ) {
if ( $i > 0 ) {
@@ -665,12 +667,16 @@
$query = "SELECT {$columns} UNION ALL " . $query;
- $result = $wpdb->query( $query );
+ $result = $GLOBALS['wpdb']->get_results( $query );
if ( false === $result ) {
return false;
}
+ if ( ! self::write_csv_to_filesystem( $filepath, $result ) ) {
+ return false;
+ }
+
return rtrim( $upload_dir['url'], '/' ) . '/' . $filename;
}
@@ -691,5 +697,32 @@
return rtrim( $upload_dir['url'], '/' ) . $filename;
}
+ /**
+ * @param string $file_path
+ * @param array $query_results
+ *
+ * @return bool
+ */
+ private static function write_csv_to_filesystem( $file_path, $query_results ) {
+ if ( empty( $query_results ) ) {
+ return false;
+ }
+
+ $content = '';
+
+ foreach ( $query_results as $row ) {
+ $row_data = array_map( function ( $value ) {
+ return str_replace( "n", ' ', $value );
+ }, (array) $row );
+ $content .= implode( "t", $row_data ) . "n";
+ }
+
+ if ( ! $GLOBALS['wp_filesystem']->put_contents( $file_path, $content, FS_CHMOD_FILE ) ) {
+ return false;
+ }
+
+ return true;
+ }
+
#endregion
}
--- a/wpgsi/includes/freemius/includes/class-fs-plugin-updater.php
+++ b/wpgsi/includes/freemius/includes/class-fs-plugin-updater.php
@@ -548,12 +548,7 @@
if ( ! isset( $this->_update_details ) ) {
// Get plugin's newest update.
- $new_version = $this->_fs->get_update(
- false,
- fs_request_get_bool( 'force-check' ),
- FS_Plugin_Updater::UPDATES_CHECK_CACHE_EXPIRATION,
- $this->_fs->get_plugin_version()
- );
+ $new_version = $this->_fs->get_update( false, fs_request_get_bool( 'force-check' ) );
$this->_update_details = false;
@@ -704,16 +699,8 @@
);
}
- if ( $this->_fs->is_premium() ) {
- $latest_tag = $this->_fs->_fetch_latest_version( $this->_fs->get_id(), false );
-
- if (
- isset( $latest_tag->readme ) &&
- isset( $latest_tag->readme->upgrade_notice ) &&
- ! empty( $latest_tag->readme->upgrade_notice )
- ) {
- $update->upgrade_notice = $latest_tag->readme->upgrade_notice;
- }
+ if ( $this->_fs->is_premium() && ! empty( $new_version->upgrade_notice ) ) {
+ $update->upgrade_notice = $new_version->upgrade_notice;
}
$update->{$this->_fs->get_module_type()} = $this->_fs->get_plugin_basename();
--- a/wpgsi/includes/freemius/includes/customizer/class-fs-customizer-upsell-control.php
+++ b/wpgsi/includes/freemius/includes/customizer/class-fs-customizer-upsell-control.php
@@ -73,7 +73,6 @@
'forum' => 'Support Forum',
'email' => 'Priority Email Support',
'phone' => 'Phone Support',
- 'skype' => 'Skype Support',
'is_success_manager' => 'Personal Success Manager',
);
--- a/wpgsi/includes/freemius/includes/entities/class-fs-payment.php
+++ b/wpgsi/includes/freemius/includes/entities/class-fs-payment.php
@@ -132,10 +132,11 @@
*/
function formatted_gross()
{
+ $price = $this->gross + $this->vat;
return (
- ( $this->gross < 0 ? '-' : '' ) .
+ ( $price < 0 ? '-' : '' ) .
$this->get_symbol() .
- number_format( abs( $this->gross ), 2, '.', ',' ) . ' ' .
+ number_format( abs( $price ), 2, '.', ',' ) . ' ' .
strtoupper( $this->currency )
);
}
--- a/wpgsi/includes/freemius/includes/entities/class-fs-plugin-plan.php
+++ b/wpgsi/includes/freemius/includes/entities/class-fs-plugin-plan.php
@@ -75,10 +75,12 @@
* @var string Support phone.
*/
public $support_phone;
- /**
- * @var string Support skype username.
- */
- public $support_skype;
+ /**
+ * @var string Support skype username.
+ *
+ * @deprecated 2.12.1
+ */
+ public $support_skype = '';
/**
* @var bool Is personal success manager supported with the plan.
*/
@@ -137,7 +139,6 @@
*/
function has_technical_support() {
return ( ! empty( $this->support_email ) ||
- ! empty( $this->support_skype ) ||
! empty( $this->support_phone ) ||
! empty( $this->is_success_manager )
);
--- a/wpgsi/includes/freemius/includes/entities/class-fs-plugin-tag.php
+++ b/wpgsi/includes/freemius/includes/entities/class-fs-plugin-tag.php
@@ -43,6 +43,10 @@
* @var string One of the following: `pending`, `beta`, `unreleased`.
*/
public $release_mode;
+ /**
+ * @var string
+ */
+ public $upgrade_notice;
function __construct( $tag = false ) {
parent::__construct( $tag );
--- a/wpgsi/includes/freemius/includes/entities/class-fs-site.php
+++ b/wpgsi/includes/freemius/includes/entities/class-fs-site.php
@@ -202,7 +202,7 @@
// Vendasta
( fs_ends_with( $subdomain, '.websitepro-staging.com' ) || fs_ends_with( $subdomain, '.websitepro.hosting' ) ) ||
// InstaWP
- fs_ends_with( $subdomain, '.instawp.xyz' ) ||
+ ( fs_ends_with( $subdomain, '.instawp.co' ) || fs_ends_with( $subdomain, '.instawp.link' ) || fs_ends_with( $subdomain, '.instawp.xyz' ) ) ||
// 10Web Hosting
( fs_ends_with( $subdomain, '-dev.10web.site' ) || fs_ends_with( $subdomain, '-dev.10web.cloud' ) )
);
@@ -220,6 +220,8 @@
// Services aimed at providing a WordPress sandbox environment.
$sandbox_wp_environment_domains = array(
// InstaWP
+ 'instawp.co',
+ 'instawp.link',
'instawp.xyz',
// TasteWP
--- a/wpgsi/includes/freemius/includes/managers/class-fs-checkout-manager.php
+++ b/wpgsi/includes/freemius/includes/managers/class-fs-checkout-manager.php
@@ -12,7 +12,36 @@
class FS_Checkout_Manager {
- # region Singleton
+ /**
+ * Allowlist of query parameters for checkout.
+ */
+ private $_allowed_custom_params = array(
+ // currency
+ 'currency' => true,
+ 'default_currency' => true,
+ // cart
+ 'always_show_renewals_amount' => true,
+ 'annual_discount' => true,
+ 'billing_cycle' => true,
+ 'billing_cycle_selector' => true,
+ 'bundle_discount' => true,
+ 'maximize_discounts' => true,
+ 'multisite_discount' => true,
+ 'show_inline_currency_selector' => true,
+ 'show_monthly' => true,
+ // appearance
+ 'form_position' => true,
+ 'is_bundle_collapsed' => true,
+ 'layout' => true,
+ 'refund_policy_position' => true,
+ 'show_refund_badge' => true,
+ 'show_reviews' => true,
+ 'show_upsells' => true,
+ 'title' => true,
+ );
+
+
+ # region Singleton
/**
* @var FS_Checkout_Manager
@@ -153,7 +182,12 @@
( $fs->is_theme() && current_user_can( 'install_themes' ) )
);
- return array_merge( $context_params, $_GET, array(
+ $filtered_params = $fs->apply_filters('checkout/parameters', $context_params);
+
+ // Allowlist only allowed query params.
+ $filtered_params = array_intersect_key($filtered_params, $this->_allowed_custom_params);
+
+ return array_merge( $context_params, $filtered_params, $_GET, array(
// Current plugin version.
'plugin_version' => $fs->get_plugin_version(),
'sdk_version' => WP_FS__SDK_VERSION,
@@ -239,4 +273,4 @@
private function get_checkout_redirect_nonce_action( Freemius $fs ) {
return $fs->get_unique_affix() . '_checkout_redirect';
}
- }
No newline at end of file
+ }
--- a/wpgsi/includes/freemius/includes/managers/class-fs-clone-manager.php
+++ b/wpgsi/includes/freemius/includes/managers/class-fs-clone-manager.php
@@ -412,12 +412,12 @@
* @author Vova Feldman (@svovaf)
* @since 2.5.0
*
- * @param Freemius $instance
- * @param string|false $license_key
+ * @param Freemius $instance
+ * @param FS_Plugin_License|null $license
*
* @return bool TRUE if successfully connected. FALSE if failed and had to restore install from backup.
*/
- private function delete_install_and_connect( Freemius $instance, $license_key = false ) {
+ private function delete_install_and_connect( Freemius $instance, $license = null ) {
$user = Freemius::_get_user_by_id( $instance->get_site()->user_id );
$instance->delete_current_install( true );
@@ -430,6 +430,9 @@
$user = Freemius::_get_user_by_email( $current_user->user_email );
}
+ $license_key = ( is_object( $license ) ? $license->secret_key : false );
+ $license_owner_id = ( is_object( $license ) ? $license->user_id : null );
+
if ( is_object( $user ) ) {
// When a clone is found, we prefer to use the same user of the original install for the opt-in.
$instance->install_with_user( $user, $license_key, false, false );
@@ -439,7 +442,14 @@
false,
false,
false,
- $license_key
+ $license_key,
+ false,
+ false,
+ false,
+ null,
+ array(),
+ true,
+ $license_owner_id
);
}
@@ -505,7 +515,7 @@
}
// If the site is a clone of another subsite in the network, or a localhost one, try to auto activate the license.
- return $this->delete_install_and_connect( $instance, $license->secret_key );
+ return $this->delete_install_and_connect( $instance, $license );
}
/**
--- a/wpgsi/includes/freemius/require.php
+++ b/wpgsi/includes/freemius/require.php
@@ -58,4 +58,5 @@
require_once WP_FS__DIR_INCLUDES . '/class-fs-admin-notices.php';
require_once WP_FS__DIR_INCLUDES . '/class-freemius-abstract.php';
require_once WP_FS__DIR_INCLUDES . '/sdk/Exceptions/Exception.php';
+ require_once WP_FS__DIR_INCLUDES . '/class-fs-hook-snapshot.php';
require_once WP_FS__DIR_INCLUDES . '/class-freemius.php';
--- a/wpgsi/includes/freemius/start.php
+++ b/wpgsi/includes/freemius/start.php
@@ -7,7 +7,7 @@
*/
if ( ! defined( 'ABSPATH' ) ) {
- ex