| @@ -131,14 +131,26 @@ | ||
| 131 | 131 | $default_options['gateway_debug_logs'] = '0'; |
| 132 | 132 | $default_options['gateway_debug_logs_extensive'] = '0'; |
| 133 | 133 | |
| 134 | 134 | $default_options['lazy_load_css_js'] = '0'; |
| 135 | + $default_options['static_css'] = '0'; //260903.0612 Generated static CSS delivery remains opt-in while frontend asset generation is beta. | |
| 136 | + $default_options['static_css_minify'] = '0'; //260902.2107 Static CSS minification is independently opt-in while generated asset delivery is beta. | |
| 137 | + $default_options['static_js'] = '0'; //260903.0437 Static frontend JavaScript delivery remains opt-in while generated assets are beta. | |
| 138 | + $default_options['static_js_text'] = 'static'; //260906.2049 Keep JavaScript text in cacheable static files by default; multilingual sites can load it with each WordPress page instead. | |
| 139 | + $default_options['static_js_minify'] = '0'; //260903.0437 Static JavaScript minification is independently opt-in and uses readable source files. | |
| 140 | + $default_options['static_assets_combine'] = '0'; //260903.1918 Keep Framework/Pro generated files separate by default; combining is an explicit request-reduction optimization. | |
| 141 | + $default_options['asset_health_wait_seconds'] = '3'; //260912.0522 Wait briefly after page load before treating an asset that cannot be confirmed active as Late. | |
| 142 | + //260904.1923 Keep the repaired s2Member Dynamic Loader as the default; WordPress routing is an explicit compatibility option. | |
| 143 | + $default_options['dynamic_asset_loader'] = 's2o'; //260910.0724 In current terminology, that established default is the s2Member-Only Dynamic Loader served by s2member-o.php. | |
| 135 | 144 | $default_options['no_cache_headers_mode'] = 'always'; //260308 No-cache headers mode: `always`, `selective`, `evaluative`. |
| 136 | 145 | $default_options['no_cache_headers_debug'] = '0'; //260308 Adds Server-Timing no-cache debug header (support use only). |
| 137 | 146 | $default_options['sc_conds_allow_arbitrary_php'] = '0'; |
| 138 | 147 | $default_options['sc_conds_whitelist'] = ''; |
| 139 | - $default_options['sc_s2get_userid_whitelist'] = ''; //260322 Comma-delimited s2Get user_field values allowed to use user_id="". | |
| 140 | 148 | |
| 149 | + //260812 New shared whitelist; keep the old s2Get option synchronized temporarily for rollback compatibility. | |
| 150 | + $default_options['sc_user_fields_whitelist'] = ''; | |
| 151 | + $default_options['sc_s2get_userid_whitelist'] = ''; | |
| 152 | + | |
| 141 | 153 | $default_options['sec_encryption_key'] = ''; |
| 142 | 154 | $default_options['sec_encryption_key_history'] = array(); |
| 143 | 155 | |
| 144 | 156 | $default_options['def_combo_encryption_key'] = ''; |
| @@ -144,8 +156,13 @@ | ||
| 144 | 156 | $default_options['def_combo_encryption_key'] = ''; |
| 145 | 157 | $default_options['def_combo_encryption_key_history'] = array(); |
| 146 | 158 | $default_options['def_custom_combo_encryption_keys'] = array(); |
| 147 | 159 | |
| 160 | + //260809 Store new Defuse key mappings by one-way hashes instead of raw secret keys. | |
| 161 | + $default_options['secret_key_to_defuse_key'] = array(); | |
| 162 | + $default_options['secret_key_to_defuse_key_history'] = array(); | |
| 163 | + $default_options['custom_secret_key_to_defuse_key'] = array(); | |
| 164 | + | |
| 148 | 165 | $default_options['s_badge_status_enabled'] = '0'; |
| 149 | 166 | |
| 150 | 167 | $default_options['max_ip_restriction'] = '5'; |
| 151 | 168 | $default_options['max_ip_restriction_time'] = '3600'; |
| @@ -365,14 +382,18 @@ | ||
| 365 | 382 | $default_options['level'.$n.'_pages'] = ''; |
| 366 | 383 | |
| 367 | 384 | $default_options['specific_ids'] = ''; |
| 368 | 385 | |
| 369 | - $default_options['triggers_immediate_eot'] = 'reversals'; | |
| 370 | - $default_options['membership_eot_behavior'] = 'demote'; | |
| 371 | - $default_options['eot_time_ext_behavior'] = 'extend'; | |
| 372 | - $default_options['auto_eot_system_enabled'] = '1'; | |
| 373 | - $default_options['eots_remove_ccaps'] = '1'; | |
| 374 | - $default_options['eot_grace_time'] = '86400'; | |
| 386 | + $default_options['triggers_immediate_eot'] = 'reversals'; | |
| 387 | + $default_options['membership_eot_behavior'] = 'demote'; | |
| 388 | + $default_options['eot_demotion_to_role'] = 'subscriber'; | |
| 389 | + $default_options['eot_demotion_from'] = 'all'; //260916.2137 Missing options must preserve legacy behavior until a fresh activation explicitly stores the new Level-only default. | |
| 390 | + $default_options['eot_time_ext_behavior'] = 'extend'; | |
| 391 | + $default_options['auto_eot_system_enabled'] = '1'; | |
| 392 | + $default_options['auto_eot_system_runtime_mode'] = 'auto'; | |
| 393 | + $default_options['auto_eot_system_runtime_custom'] = '30'; | |
| 394 | + $default_options['eots_remove_ccaps'] = '1'; | |
| 395 | + $default_options['eot_grace_time'] = '86400'; | |
| 375 | 396 | |
| 376 | 397 | $default_options['wp_footer_code'] = ''; |
| 377 | 398 | |
| 378 | 399 | $default_options = apply_filters('ws_plugin__s2member_default_options', $default_options); |
| @@ -380,9 +401,21 @@ | ||
| 380 | 401 | unset($n, $v, $l); // Unset/cleanup these working variables from the routines above. |
| 381 | 402 | /* |
| 382 | 403 | Here they are merged. User options will overwrite some or all default values. |
| 383 | 404 | */ |
| 384 | - $GLOBALS['WS_PLUGIN__']['s2member']['o'] = array_merge($default_options, (($options !== FALSE) ? (array)$options : (array)get_option('ws_plugin__s2member_options'))); | |
| 405 | + $_stored_options = (($options !== FALSE) ? (array)$options : (array)get_option('ws_plugin__s2member_options')); | |
| 406 | + $GLOBALS['WS_PLUGIN__']['s2member']['o'] = array_merge($default_options, $_stored_options); | |
| 407 | + | |
| 408 | + //260812 Keep both whitelist option names synchronized, with the legacy value taking precedence after a rollback. | |
| 409 | + if(isset($_stored_options['sc_s2get_userid_whitelist']) && is_string($_stored_options['sc_s2get_userid_whitelist'])) | |
| 410 | + { | |
| 411 | + if(!array_key_exists('sc_user_fields_whitelist', $_stored_options) || $GLOBALS['WS_PLUGIN__']['s2member']['o']['sc_user_fields_whitelist'] !== $_stored_options['sc_s2get_userid_whitelist']) | |
| 412 | + $GLOBALS['WS_PLUGIN__']['s2member']['o']['sc_user_fields_whitelist'] = $_stored_options['sc_s2get_userid_whitelist']; | |
| 413 | + } | |
| 414 | + else if(isset($_stored_options['sc_user_fields_whitelist']) && is_string($_stored_options['sc_user_fields_whitelist'])) | |
| 415 | + $GLOBALS['WS_PLUGIN__']['s2member']['o']['sc_s2get_userid_whitelist'] = $_stored_options['sc_user_fields_whitelist']; | |
| 416 | + unset($_stored_options); | |
| 417 | + | |
| 385 | 418 | /* |
| 386 | 419 | * Ditch this old option key; no longer in use. |
| 387 | 420 | */ |
| 388 | 421 | if(isset($GLOBALS['WS_PLUGIN__']['s2member']['o']['run_deactivation_routines'])) unset($GLOBALS['WS_PLUGIN__']['s2member']['o']['run_deactivation_routines']); |
| @@ -411,8 +444,16 @@ | ||
| 411 | 444 | |
| 412 | 445 | else if($key === 'lazy_load_css_js' && (!is_string($value) || !is_numeric($value))) |
| 413 | 446 | $value = $default_options[$key]; |
| 414 | 447 | |
| 448 | + else if(preg_match('/^static_(?:css|js)(?:_minify)?$/', $key) && (!is_string($value) || !is_numeric($value))) //260903.0437 | |
| 449 | + $value = $default_options[$key]; | |
| 450 | + | |
| 451 | + //260912.0522 Keep the operator-facing wait bounded so an accidental value cannot effectively disable health checking. | |
| 452 | + //260911.0010 Here, bounded means the explicit 1–60-second range exposed by the setting. | |
| 453 | + else if($key === 'asset_health_wait_seconds') | |
| 454 | + $value = (!is_string($value) || !is_numeric($value) || (int)$value < 1 || (int)$value > 60) ? $default_options[$key] : (string)(int)$value; | |
| 455 | + | |
| 415 | 456 | else if($key === 'no_cache_headers_mode' && (!is_string($value) || !in_array($value, array('always', 'selective', 'evaluative'), TRUE))) |
| 416 | 457 | $value = $default_options[$key]; |
| 417 | 458 | |
| 418 | 459 | else if($key === 'no_cache_headers_debug' && (!is_string($value) || !is_numeric($value))) |
| @@ -422,8 +463,10 @@ | ||
| 422 | 463 | $value = $default_options[$key]; |
| 423 | 464 | |
| 424 | 465 | else if($key === 'sc_s2get_userid_whitelist' && !is_string($value)) //260324 |
| 425 | 466 | $value = $default_options[$key]; |
| 467 | + else if($key === 'sc_user_fields_whitelist' && !is_string($value)) //260812 | |
| 468 | + $value = $default_options[$key]; | |
| 426 | 469 | |
| 427 | 470 | else if($key === 'sec_encryption_key' && (!is_string($value) || !strlen($value))) |
| 428 | 471 | $value = $default_options[$key]; |
| 429 | 472 | |
| @@ -438,8 +481,12 @@ | ||
| 438 | 481 | |
| 439 | 482 | else if($key === 'def_custom_combo_encryption_keys' && (!is_array($value) || empty($value))) |
| 440 | 483 | $value = $default_options[$key]; |
| 441 | 484 | |
| 485 | + //260809 Validate the hashed Defuse key mappings independently of the legacy options. | |
| 486 | + else if(preg_match('/^(?:secret_key_to_defuse_key|secret_key_to_defuse_key_history|custom_secret_key_to_defuse_key)$/', $key) && (!is_array($value) || empty($value))) | |
| 487 | + $value = $default_options[$key]; | |
| 488 | + | |
| 442 | 489 | else if($key === 's_badge_status_enabled' && (!is_string($value) || !is_numeric($value))) |
| 443 | 490 | $value = $default_options[$key]; |
| 444 | 491 | |
| 445 | 492 | else if($key === 'max_ip_restriction' && (!is_string($value) || !is_numeric($value) || $value < 0 || $value > 100)) |
| @@ -648,11 +695,24 @@ | ||
| 648 | 695 | |
| 649 | 696 | else if($key === 'membership_eot_behavior' && (!is_string($value) || !preg_match('/^(?:demote|delete)$/', $value))) |
| 650 | 697 | $value = $default_options[$key]; |
| 651 | 698 | |
| 699 | + //260916.2306 Keep bootstrap validation side-effect free; role existence is checked later when the EOT demotion role is resolved, after s2Member is fully loaded. | |
| 700 | + else if($key === 'eot_demotion_to_role' && (!is_string($value) || !$value || in_array($value, array('administrator', 'editor', 'author', 'contributor', 's2member_pending_deletion'), TRUE))) | |
| 701 | + $value = $default_options[$key]; | |
| 702 | + | |
| 703 | + else if($key === 'eot_demotion_from' && (!is_string($value) || !preg_match('/^(?:s2member_level|all)$/', $value))) | |
| 704 | + $value = $default_options[$key]; | |
| 705 | + | |
| 652 | 706 | else if($key === 'eot_time_ext_behavior' && (!is_string($value) || !preg_match('/^(?:extend|reset)$/', $value))) |
| 653 | 707 | $value = $default_options[$key]; |
| 654 | 708 | |
| 709 | + else if($key === 'auto_eot_system_runtime_mode' && (!is_string($value) || !preg_match('/^(?:auto|custom)$/', $value))) | |
| 710 | + $value = $default_options[$key]; | |
| 711 | + | |
| 712 | + else if($key === 'auto_eot_system_runtime_custom' && (!is_string($value) || !is_numeric($value) || (float)$value < 1 || (float)$value > 3600)) | |
| 713 | + $value = $default_options[$key]; | |
| 714 | + | |
| 655 | 715 | else if(preg_match('/^(?:auto_eot_system_enabled|eot_grace_time|eots_remove_ccaps)$/', $key) && (!is_string($value) || !is_numeric($value))) |
| 656 | 716 | $value = $default_options[$key]; |
| 657 | 717 | |
| 658 | 718 | else if($key === 'wp_footer_code' && (!is_string($value) || !strlen($value))) |
| @@ -664,8 +724,13 @@ | ||
| 664 | 724 | } |
| 665 | 725 | if($options !== FALSE && is_string($options['def_combo_encryption_key']) && strlen($options['def_combo_encryption_key']) && !in_array($options['def_combo_encryption_key'], $GLOBALS['WS_PLUGIN__']['s2member']['o']['def_combo_encryption_key_history'])) { |
| 666 | 726 | array_unshift($GLOBALS['WS_PLUGIN__']['s2member']['o']['def_combo_encryption_key_history'], $options['def_combo_encryption_key']); |
| 667 | 727 | $GLOBALS['WS_PLUGIN__']['s2member']['o']['def_combo_encryption_key_history'] = array_slice($GLOBALS['WS_PLUGIN__']['s2member']['o']['def_combo_encryption_key_history'], 0, 10); |
| 728 | + } | |
| 729 | + //260809 Keep a recovery-only history of default hashed Defuse key mappings. | |
| 730 | + if($options !== FALSE && is_array($options['secret_key_to_defuse_key']) && !empty($options['secret_key_to_defuse_key']) && !in_array($options['secret_key_to_defuse_key'], $GLOBALS['WS_PLUGIN__']['s2member']['o']['secret_key_to_defuse_key_history'], TRUE)) { | |
| 731 | + array_unshift($GLOBALS['WS_PLUGIN__']['s2member']['o']['secret_key_to_defuse_key_history'], $options['secret_key_to_defuse_key']); | |
| 732 | + $GLOBALS['WS_PLUGIN__']['s2member']['o']['secret_key_to_defuse_key_history'] = array_slice($GLOBALS['WS_PLUGIN__']['s2member']['o']['secret_key_to_defuse_key_history'], 0, 10); | |
| 668 | 733 | } |
| 669 | 734 | $GLOBALS['WS_PLUGIN__']['s2member']['o'] = apply_filters_ref_array('ws_plugin__s2member_options_before_checksum', array(&$GLOBALS['WS_PLUGIN__']['s2member']['o'])); |
| 670 | 735 | |
| 671 | 736 | $GLOBALS['WS_PLUGIN__']['s2member']['o']['options_checksum'] = md5($checksum_prefix.serialize(array_merge($GLOBALS['WS_PLUGIN__']['s2member']['o'], array('options_checksum' => 0)))); |