============================================================
# WAPF Extended v3.1.5 — License Bypass Task Log
# ============================================================
# Date: 2026-09-05
# Plugin version: Advanced Product Fields Extended for WooCommerce 3.1.5
# Problem: Plugin requires a license key for all features to work
# Solution: Targeted bypass based on analysis of the Pro 3.1.2 version
# ============================================================
# -----------------------------------------------------------
# SYMPTOMS
# -----------------------------------------------------------
# - "Custom fields" tab in WooCommerce product editor showed
# "Please activate your license first"
# - "Add your first field" button did not work
# - Red overlay: "It appears you are using the paid version
# without a valid license. Features are temporarily disabled."
# - All settings (General, Design) were hidden
# - Field groups list was not displayed
# -----------------------------------------------------------
# ANALYSIS: HOW LICENSE CHECKING WORKS
# -----------------------------------------------------------
# The plugin uses a SINGLE source-of-truth function:
#
# Licensing::get_license_info()
# -> reads wp_options[advanced-product-fields-for-woocommerce-pro_license]
# -> returns object {key, expiration, url} or null
#
# ALL checks in the plugin (25+ locations) boil down to:
# $has_license = Licensing::get_license_info() != null
#
# PHP checks:
# 1. class-admin-controller.php:521 — field editor (feature gate)
# 2. class-admin-controller.php:590 — settings tabs
# 3. class-admin-controller.php:671 — settings array
# 4. class-admin-controller.php:1284 — field groups list
# 5. class-admin-controller.php:438 — plugin action links
# 6. class-admin-controller.php:334 — passing key to JS
#
# JS checks (in obfuscated admin.min.js):
# 1. Function WhNBkbUCQshUSgmLkhTSmFYa() — validates the key
# - Reads localStorage for cached result
# - Validates key format (length >= 20, must contain '-')
# - Makes fetch() to api.studiowombat.com
# - Calls IGEvEhYg_Q_RazISpEAxzOPPPU(true/false)
# which sets the global can = true/false
# 2. When can = false, the div .wapf-block-pro is shown
# 3. When can = false, Rivets.js controllers do not initialize
# -----------------------------------------------------------
# SOLUTION: 5 EDITS IN 4 FILES
# -----------------------------------------------------------
changes:
- id: 1
file: includes/classes/class-licensing.php
method: get_license_info()
line: 41-44
description: >
Core bypass. When no license record exists in the database
(raw === false), return a fake license object with a key
and expiration +10 years. This bypasses ALL 25+ PHP checks.
before: |
public static function get_license_info() {
$raw = get_option( 'advanced-product-fields-for-woocommerce-pro_license' );
return $raw === false ? null : json_decode( base64_decode( $raw ) );
}
after: |
public static function get_license_info() {
$raw = get_option( 'advanced-product-fields-for-woocommerce-pro_license' );
if ($raw === false) {
return (object) [
'key' => 'wapf-local-bypass-key-12345-67890',
'expiration' => date('Y-m-d H:i:s', strtotime('+10 years')),
'url' => home_url()
];
}
return json_decode( base64_decode( $raw ) );
}
- id: 2
file: includes/controllers/class-admin-controller.php
method: register_assets()
line: 331-338
description: >
The fake key is NOT passed to JavaScript.
If the fake key were sent via wapf_config.key, the JS
validation would reject it and show the overlay.
An empty string '' passes JS validation without errors.
before: |
$info = Licensing::get_license_info();
$key = $info !== null && ! empty( $info->key ) ? $info->key : '';
wp_localize_script( 'wapf-admin-js', 'wapf_config', [
'ajaxUrl' => admin_url( 'admin-ajax.php' ),
'isWooProductScreen' => $this->is_screen('product'),
'key' => $key
]);
after: |
$info = Licensing::get_license_info();
$key = $info !== null && ! empty( $info->key ) ? $info->key : '';
$is_bypassed = $info !== null && isset($info->key) && strpos($info->key, 'local-bypass') !== false;
$js_key = $is_bypassed ? '' : $key;
wp_localize_script( 'wapf-admin-js', 'wapf_config', [
'ajaxUrl' => admin_url( 'admin-ajax.php' ),
'isWooProductScreen' => $this->is_screen('product'),
'key' => $js_key
]);
- id: 3
file: views/admin/licensing.php
line: 1-36
description: >
Remove the key input field and Activate/Deactivate buttons.
Replace with a readonly field showing *************** and
the text "License is active." Prevents accidental
deactivation of the bypass.
before: |
Full file content with input field + Activate/Deactivate buttons
after: |
Readonly input "***************" + text "License is active."
- id: 4
file: views/admin/field-list.php
line: 42-48
description: >
Remove the div.wapf-block-pro containing the red warning
banner about invalid license. This element is no longer
needed since the license is always considered valid.
removed_html: |
<div class="wapf-block-pro" style="display: none;...">
<span><strong style="color: #fff;">
It appears you are using the paid version without a valid license...
</strong></span>
</div>
- id: 5
file: assets/js/admin.min.js
function: WhNBkbUCQshUSgmLkhTSmFYa
description: >
Replace the body of the JS license check function.
The original function (2,166 characters) performed:
- localStorage cache read
- key format validation
- fetch() to api.studiowombat.com
- setting can = true/false
The new function (68 characters) simply calls
IGEvEhYg_Q_RazISpEAxzOPPPU(true) which sets can = true.
This disables ALL JS license validation.
before: |
function WhNBkbUCQshUSgmLkhTSmFYa(){var OFMhYbRek$oydlvG=...2166 chars...);}
after: |
function WhNBkbUCQshUSgmLkhTSmFYa(){IGEvEhYg_Q_RazISpEAxzOPPPU(!0);}
# -----------------------------------------------------------
# WHY THIS APPROACH
# -----------------------------------------------------------
# The approach was developed by comparing the working Pro 3.1.2
# version (by flopas10 for nullcave.club) with the original
# Extended 3.1.5.
#
# Pro 3.1.2 used THE SAME approach:
# 1. get_license_info() — fake object
# 2. register_assets() — empty key for JS
# 3. licensing.php — readonly + "activated"
# 4. admin.unminified.js — minified function with can=true
# 5. field-list.php — div .wapf-block-pro removed
#
# Our edits are logically identical, adapted for v3.1.5.
# -----------------------------------------------------------
# TESTING
# -----------------------------------------------------------
# After applying changes, verify:
# [x] "Custom fields" tab in product editor renders
# [x] "Add your first field" button works
# [x] "Add a Field" button works
# [x] Red .wapf-block-pro overlay does not appear
# [x] WooCommerce settings (General | Design) are accessible
# [x] Field groups list is displayed
# [x] License form shows "License is active."
# -----------------------------------------------------------
# RISKS AND LIMITATIONS
# -----------------------------------------------------------
# - WordPress plugin updates will overwrite the edits
# - The fake key does not pass remote API validation
# - If the wp_options table is dropped, the license "expires"
# but get_license_info() returns a fake object again
# -----------------------------------------------------------
# FILES
# -----------------------------------------------------------
# Modified files (relative to plugin root):
# 1. includes/classes/class-licensing.php (get_license_info)
# 2. includes/controllers/class-admin-controller.php (register_assets)
# 3. views/admin/licensing.php (license form)
# 4. views/admin/field-list.php (removed overlay)
# 5. assets/js/admin.min.js (check function)