Changeset 3761091
- Timestamp:
- 10/23/2026 07:24:04 AM (68 minutes ago)
- Location:
- stop-user-enumeration
- Files:
-
- 2 added
- 24 edited
- 1 copied
-
tags/1.7.10 (copied) (copied from stop-user-enumeration/trunk )
-
tags/1.7.10/changelog.txt (modified) (1 diff)
-
tags/1.7.10/includes/vendor/alanef/free_plugin_lib/.wp-env.json (added)
-
tags/1.7.10/includes/vendor/alanef/free_plugin_lib/src/Assets/scripts/main.js (modified) (1 diff)
-
tags/1.7.10/includes/vendor/alanef/free_plugin_lib/src/Classes/Email.php (modified) (3 diffs)
-
tags/1.7.10/includes/vendor/alanef/free_plugin_lib/src/Main.php (modified) (19 diffs)
-
tags/1.7.10/includes/vendor/autoload.php (modified) (1 diff)
-
tags/1.7.10/includes/vendor/composer/autoload_real.php (modified) (2 diffs)
-
tags/1.7.10/includes/vendor/composer/autoload_static.php (modified) (2 diffs)
-
tags/1.7.10/includes/vendor/composer/installed.json (modified) (3 diffs)
-
tags/1.7.10/includes/vendor/composer/installed.php (modified) (3 diffs)
-
tags/1.7.10/languages/stop-user-enumeration.pot (modified) (1 diff)
-
tags/1.7.10/readme.txt (modified) (1 diff)
-
tags/1.7.10/stop-user-enumeration.php (modified) (2 diffs)
-
trunk/changelog.txt (modified) (1 diff)
-
trunk/includes/vendor/alanef/free_plugin_lib/.wp-env.json (added)
-
trunk/includes/vendor/alanef/free_plugin_lib/src/Assets/scripts/main.js (modified) (1 diff)
-
trunk/includes/vendor/alanef/free_plugin_lib/src/Classes/Email.php (modified) (3 diffs)
-
trunk/includes/vendor/alanef/free_plugin_lib/src/Main.php (modified) (19 diffs)
-
trunk/includes/vendor/autoload.php (modified) (1 diff)
-
trunk/includes/vendor/composer/autoload_real.php (modified) (2 diffs)
-
trunk/includes/vendor/composer/autoload_static.php (modified) (2 diffs)
-
trunk/includes/vendor/composer/installed.json (modified) (3 diffs)
-
trunk/includes/vendor/composer/installed.php (modified) (3 diffs)
-
trunk/languages/stop-user-enumeration.pot (modified) (1 diff)
-
trunk/readme.txt (modified) (1 diff)
-
trunk/stop-user-enumeration.php (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
stop-user-enumeration/tags/1.7.10/changelog.txt
r3724500 r3761091 1 1 == Changelog == 2 = 1.7.10 = 3 * Fixed: the settings notice could not be dismissed and kept coming back on every page load 4 * Fixed: on sites running other Fullworks free plugins, the opt-in notice and menu could belong to the wrong plugin 5 * Fixed: leaving the opt-in screen without choosing left the notice up for good; visiting settings now shows the opt-in screen again until you click Allow or Skip 6 * Changed: the notice now links straight to the opt-in screen instead of the settings page 7 * Changed: updated the bundled opt-in library to 1.3.2 8 2 9 = 1.7.9 = 3 10 * Fixed two database writes on every page load: the plugin and its bundled opt-in library both registered an uninstall hook and overwrote each other's entry in the uninstall_plugins option. Uninstall now runs from uninstall.php instead -
stop-user-enumeration/tags/1.7.10/includes/vendor/alanef/free_plugin_lib/src/Assets/scripts/main.js
r3259418 r3761091 29 29 action: 'ffpl_handle_optin', 30 30 email: email, 31 shortname: ffplData.shortname, 31 32 nonce: ffplData.nonce 32 33 }, -
stop-user-enumeration/tags/1.7.10/includes/vendor/alanef/free_plugin_lib/src/Classes/Email.php
r3679961 r3761091 4 4 5 5 class Email { 6 private static$plugin_shortname;6 private $plugin_shortname; 7 7 8 8 // Plugin shortname to ID mapping … … 20 20 21 21 public function __construct($plugin_shortname) { 22 self::$plugin_shortname = $plugin_shortname;22 $this->plugin_shortname = $plugin_shortname; 23 23 } 24 24 … … 33 33 34 34 // Get plugin ID from map 35 $plugin_id = $plugin_map[ self::$plugin_shortname] ?? null;35 $plugin_id = $plugin_map[$this->plugin_shortname] ?? null; 36 36 if (!$plugin_id) { 37 37 return false; -
stop-user-enumeration/tags/1.7.10/includes/vendor/alanef/free_plugin_lib/src/Main.php
r3724500 r3761091 7 7 class Main { 8 8 /** 9 * Shortname of the most recently constructed instance, used only as the default for 10 * plugin_uninstall(). Every plugin bundling this library shares one copy of the class, 11 * so per-plugin state must live on the instance, never here. 12 * 9 13 * @var mixed 10 14 */ 11 private static $plugin_shortname; 15 private static $last_plugin_shortname; 16 /** 17 * @var mixed 18 */ 19 private $plugin_shortname; 12 20 /** 13 21 * @var string 14 22 */ 15 private static $version = '1.3.0'; 16 /** 23 private static $version = '1.3.2'; 24 /** 25 * The host plugin's settings page as passed: a menu slug ('stop-user-enumeration'), a hook 26 * suffix ('settings_page_contact-form-settings') or '' for a plugin with no settings page. 27 * 17 28 * @var mixed 18 29 */ 19 30 private $page; 31 /** 32 * The menu slug part of $page, compared with $_GET['page']. 33 * 34 * @var string 35 */ 36 private $page_slug; 20 37 /** 21 38 * @var \WP_Screen|null … … 33 50 34 51 public function __construct($plugin_file, $settings_page, $plugin_shortname, $page, $plugin_name) { 35 self::$plugin_shortname = $plugin_shortname; 52 $this->plugin_shortname = $plugin_shortname; 53 self::$last_plugin_shortname = $plugin_shortname; 36 54 $this->page = $page; 55 $this->page_slug = (string) preg_replace('/^.*_page_/', '', (string) $page); 37 56 $this->plugin_file = $plugin_file; 38 57 $this->settings_page = $settings_page; … … 67 86 */ 68 87 public static function plugin_uninstall($plugin_shortname = null) { 69 $plugin_shortname = null === $plugin_shortname ? self::$ plugin_shortname : $plugin_shortname;88 $plugin_shortname = null === $plugin_shortname ? self::$last_plugin_shortname : $plugin_shortname; 70 89 if (empty($plugin_shortname)) { 71 90 return; … … 81 100 // Verify nonce - the nonce IS the ffpl_skip value 82 101 $nonce = sanitize_text_field(wp_unslash($_GET['ffpl_skip'])); 83 if (!wp_verify_nonce($nonce, 'ffpl_skip_' . self::$plugin_shortname)) {102 if (!wp_verify_nonce($nonce, 'ffpl_skip_' . $this->plugin_shortname)) { 84 103 return; 85 104 } 86 105 87 106 // Set status to optout - user explicitly skipped 88 update_site_option( self::$plugin_shortname . '_form_rendered', 'optout');107 update_site_option($this->plugin_shortname . '_form_rendered', 'optout'); 89 108 90 109 // Redirect to clean URL (remove the skip param) … … 94 113 95 114 public function handle_optin_page() { 115 // admin_init also runs for admin-ajax.php, and a redirect there breaks every AJAX call on the site 116 if (wp_doing_ajax() || '' === $this->page_slug || !current_user_can('manage_options')) { 117 return; 118 } 119 96 120 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- This is page routing, not form processing 97 121 $current_page = isset($_GET['page']) ? sanitize_text_field(wp_unslash($_GET['page'])) : ''; 98 $option = get_site_option(self::$plugin_shortname . '_form_rendered'); 99 if ('pending' === $option && $current_page === $this->page) { 100 update_site_option(self::$plugin_shortname . '_form_rendered', 'rendering'); 101 wp_safe_redirect(admin_url('options-general.php?page=ffpl-opt-in-' . self::$plugin_shortname)); 122 $option = get_site_option($this->plugin_shortname . '_form_rendered'); 123 // 'rendering' means the opt-in screen was shown but left without a choice, so ask again 124 if (in_array($option, array('pending', 'rendering'), true) && $current_page === $this->page_slug) { 125 update_site_option($this->plugin_shortname . '_form_rendered', 'rendering'); 126 wp_safe_redirect(admin_url('options-general.php?page=ffpl-opt-in-' . $this->plugin_shortname)); 102 127 exit; 103 128 } … … 110 135 $settings_link 111 136 ); 112 if ('optout' === get_site_option( self::$plugin_shortname . '_form_rendered', 'optout')) {113 $settings_link = '<a href="' . esc_url(admin_url('options-general.php?page=ffpl-opt-in-'. self::$plugin_shortname )) . '" style="font-weight:900; font-size: 110%; color: #b32d2e;">' . esc_html($this->translate('Opt In')) . '</a>';137 if ('optout' === get_site_option($this->plugin_shortname . '_form_rendered', 'optout')) { 138 $settings_link = '<a href="' . esc_url(admin_url('options-general.php?page=ffpl-opt-in-'.$this->plugin_shortname )) . '" style="font-weight:900; font-size: 110%; color: #b32d2e;">' . esc_html($this->translate('Opt In')) . '</a>'; 114 139 array_unshift( 115 140 $links, … … 123 148 public function add_settings_page() { 124 149 // First-run detection - if option doesn't exist, set to pending 125 $option = get_site_option( self::$plugin_shortname . '_form_rendered');150 $option = get_site_option($this->plugin_shortname . '_form_rendered'); 126 151 if (false === $option) { 127 update_site_option( self::$plugin_shortname . '_form_rendered', 'pending');152 update_site_option($this->plugin_shortname . '_form_rendered', 'pending'); 128 153 $option = 'pending'; 129 154 } … … 135 160 esc_html($this->translate('Opt In ') . esc_html( $this->plugin_name) ), // Menu title 136 161 'manage_options', // Capability 137 'ffpl-opt-in-'. self::$plugin_shortname, // Menu slug162 'ffpl-opt-in-'.$this->plugin_shortname, // Menu slug 138 163 array($this, 'render_opt_in_page') // Callback function 139 164 ); … … 200 225 </div> 201 226 <div class="button-2"> 202 <a href="<?php echo esc_url(add_query_arg('ffpl_skip', wp_create_nonce('ffpl_skip_' . self::$plugin_shortname), $this->settings_page)); ?>"227 <a href="<?php echo esc_url(add_query_arg('ffpl_skip', wp_create_nonce('ffpl_skip_' . $this->plugin_shortname), $this->settings_page)); ?>" 203 228 class="button button-secondary btn-skip" name="action" value="skip" 204 229 tabindex="2"> … … 241 266 public function conditional_enqueue_assets($hook) { 242 267 // Only load on our specific page 243 if ($hook !== 'settings_page_ffpl-opt-in-'. self::$plugin_shortname) {268 if ($hook !== 'settings_page_ffpl-opt-in-'.$this->plugin_shortname) { 244 269 return; 245 270 } … … 260 285 'ajaxurl' => admin_url('admin-ajax.php'), 261 286 'nonce' => wp_create_nonce('ffpl_optin_nonce'), 287 'shortname' => $this->plugin_shortname, 262 288 'settings_page' => $this->settings_page 263 289 )); … … 265 291 266 292 public function handle_optin_ajax() { 293 // Every plugin bundling the library registers this handler; leave other plugins' requests to them 294 if (isset($_POST['shortname']) && !$this->is_own_shortname(sanitize_key(wp_unslash($_POST['shortname'])))) { 295 return; 296 } 297 267 298 // Verify request method 268 299 if (!isset($_SERVER['REQUEST_METHOD']) || $_SERVER['REQUEST_METHOD'] !== 'POST') { … … 297 328 $email = isset($_POST['email']) ? sanitize_email(wp_unslash($_POST['email'])) : ''; 298 329 299 $email_handler = new Email( self::$plugin_shortname);330 $email_handler = new Email($this->plugin_shortname); 300 331 $result = $email_handler->handle_optin_submission($email); 301 332 302 333 if ($result) { 303 update_site_option( self::$plugin_shortname . '_form_rendered', 'optin');334 update_site_option($this->plugin_shortname . '_form_rendered', 'optin'); 304 335 wp_send_json_success(array( 305 336 'redirect_url' => $this->settings_page 306 337 )); 307 338 } else { 308 update_site_option( self::$plugin_shortname . '_form_rendered', 'optout');339 update_site_option($this->plugin_shortname . '_form_rendered', 'optout'); 309 340 wp_send_json_success(array( 310 341 'redirect_url' => $this->settings_page … … 325 356 } 326 357 327 $option = get_site_option( self::$plugin_shortname . '_form_rendered');358 $option = get_site_option($this->plugin_shortname . '_form_rendered'); 328 359 329 360 // Only show notice if no decision has been made yet (pending or rendering) … … 334 365 335 366 // Don't show if user dismissed the notice 336 if (get_user_meta(get_current_user_id(), self::$plugin_shortname . '_notice_dismissed', true)) {367 if (get_user_meta(get_current_user_id(), $this->plugin_shortname . '_notice_dismissed', true)) { 337 368 return; 338 369 } … … 345 376 'tools', 346 377 'options-general', 347 'settings_page_' . $this->page,348 378 ); 379 if ('' !== $this->page_slug) { 380 // A hook suffix is already the screen base; a menu slug is assumed to be under Settings 381 $display_on_pages[] = $this->page === $this->page_slug ? 'settings_page_' . $this->page : $this->page; 382 } 349 383 350 384 if (!in_array($page, $display_on_pages, true)) { … … 352 386 } 353 387 354 $opt_in_url = admin_url('options-general.php?page=ffpl-opt-in-' . self::$plugin_shortname);388 $opt_in_url = admin_url('options-general.php?page=ffpl-opt-in-' . $this->plugin_shortname); 355 389 ?> 356 <div class="notice notice-info is-dismissible ffpl-setup-notice" data-shortname="<?php echo esc_attr( self::$plugin_shortname); ?>">390 <div class="notice notice-info is-dismissible ffpl-setup-notice" data-shortname="<?php echo esc_attr($this->plugin_shortname); ?>"> 357 391 <p> 358 392 <strong><?php echo esc_html($this->plugin_name); ?>:</strong> 359 393 <?php 360 394 printf( 361 '%s <a href="%s"><strong>%s</strong></a> %s', 362 esc_html($this->translate('You haven\'t visited settings yet.')), 363 esc_url($this->settings_page), 364 esc_html($this->translate('Please check your settings')), 365 esc_html($this->translate('for optimal configuration and opt in for security updates, tips and occasional offers.')) 395 '%s <a href="%s"><strong>%s</strong></a>', 396 esc_html($this->translate('Choose whether to receive security updates, tips and occasional offers.')), 397 esc_url($opt_in_url), 398 esc_html($this->translate('Opt in or skip')) 366 399 ); 367 400 ?> … … 370 403 <script> 371 404 jQuery(document).ready(function($) { 372 $('.ffpl-setup-notice').on('click', '.notice-dismiss', function() { 373 var shortname = $(this).closest('.ffpl-setup-notice').data('shortname'); 405 $('.ffpl-setup-notice[data-shortname="<?php echo esc_js($this->plugin_shortname); ?>"]').on('click', '.notice-dismiss', function() { 374 406 $.post(ajaxurl, { 375 407 action: 'ffpl_dismiss_notice', 376 shortname: shortname,408 shortname: '<?php echo esc_js($this->plugin_shortname); ?>', 377 409 nonce: '<?php echo esc_js(wp_create_nonce('ffpl_dismiss_notice')); ?>' 378 410 }); … … 394 426 } 395 427 396 $shortname = isset($_POST['shortname']) ? sanitize_key($_POST['shortname']) : ''; 397 if ($shortname === self::$plugin_shortname) { 398 update_user_meta(get_current_user_id(), self::$plugin_shortname . '_notice_dismissed', true); 399 wp_send_json_success(); 400 } 401 402 wp_send_json_error(); 428 // Every plugin bundling the library registers this handler; leave other plugins' requests to them 429 $shortname = isset($_POST['shortname']) ? sanitize_key(wp_unslash($_POST['shortname'])) : ''; 430 if (!$this->is_own_shortname($shortname)) { 431 return; 432 } 433 434 // The meta key keeps the shortname's original case so existing dismissals stay readable 435 update_user_meta(get_current_user_id(), $this->plugin_shortname . '_notice_dismissed', true); 436 wp_send_json_success(); 403 437 wp_die(); 438 } 439 440 /** 441 * sanitize_key() lowercases, and host plugins pass mixed-case shortnames such as 'SUE'. 442 * 443 * @param string $shortname A shortname that has been through sanitize_key(). 444 */ 445 private function is_own_shortname($shortname) { 446 return '' !== $shortname && $shortname === sanitize_key($this->plugin_shortname); 404 447 } 405 448 -
stop-user-enumeration/tags/1.7.10/includes/vendor/autoload.php
r3724500 r3761091 20 20 require_once __DIR__ . '/composer/autoload_real.php'; 21 21 22 return ComposerAutoloaderInit 09347b3d36fb9de9d34777796c5e08ee::getLoader();22 return ComposerAutoloaderInit3836c91313ab2ce66e7903b7eb493963::getLoader(); -
stop-user-enumeration/tags/1.7.10/includes/vendor/composer/autoload_real.php
r3724500 r3761091 3 3 // autoload_real.php @generated by Composer 4 4 5 class ComposerAutoloaderInit 09347b3d36fb9de9d34777796c5e08ee5 class ComposerAutoloaderInit3836c91313ab2ce66e7903b7eb493963 6 6 { 7 7 private static $loader; … … 25 25 require __DIR__ . '/platform_check.php'; 26 26 27 spl_autoload_register(array('ComposerAutoloaderInit 09347b3d36fb9de9d34777796c5e08ee', 'loadClassLoader'), true, true);27 spl_autoload_register(array('ComposerAutoloaderInit3836c91313ab2ce66e7903b7eb493963', 'loadClassLoader'), true, true); 28 28 self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__)); 29 spl_autoload_unregister(array('ComposerAutoloaderInit 09347b3d36fb9de9d34777796c5e08ee', 'loadClassLoader'));29 spl_autoload_unregister(array('ComposerAutoloaderInit3836c91313ab2ce66e7903b7eb493963', 'loadClassLoader')); 30 30 31 31 require __DIR__ . '/autoload_static.php'; 32 call_user_func(\Composer\Autoload\ComposerStaticInit 09347b3d36fb9de9d34777796c5e08ee::getInitializer($loader));32 call_user_func(\Composer\Autoload\ComposerStaticInit3836c91313ab2ce66e7903b7eb493963::getInitializer($loader)); 33 33 34 34 $loader->register(true); -
stop-user-enumeration/tags/1.7.10/includes/vendor/composer/autoload_static.php
r3724500 r3761091 5 5 namespace Composer\Autoload; 6 6 7 class ComposerStaticInit 09347b3d36fb9de9d34777796c5e08ee7 class ComposerStaticInit3836c91313ab2ce66e7903b7eb493963 8 8 { 9 9 public static $prefixLengthsPsr4 = array ( … … 88 88 { 89 89 return \Closure::bind(function () use ($loader) { 90 $loader->prefixLengthsPsr4 = ComposerStaticInit 09347b3d36fb9de9d34777796c5e08ee::$prefixLengthsPsr4;91 $loader->prefixDirsPsr4 = ComposerStaticInit 09347b3d36fb9de9d34777796c5e08ee::$prefixDirsPsr4;92 $loader->prefixesPsr0 = ComposerStaticInit 09347b3d36fb9de9d34777796c5e08ee::$prefixesPsr0;93 $loader->classMap = ComposerStaticInit 09347b3d36fb9de9d34777796c5e08ee::$classMap;90 $loader->prefixLengthsPsr4 = ComposerStaticInit3836c91313ab2ce66e7903b7eb493963::$prefixLengthsPsr4; 91 $loader->prefixDirsPsr4 = ComposerStaticInit3836c91313ab2ce66e7903b7eb493963::$prefixDirsPsr4; 92 $loader->prefixesPsr0 = ComposerStaticInit3836c91313ab2ce66e7903b7eb493963::$prefixesPsr0; 93 $loader->classMap = ComposerStaticInit3836c91313ab2ce66e7903b7eb493963::$classMap; 94 94 95 95 }, null, ClassLoader::class); -
stop-user-enumeration/tags/1.7.10/includes/vendor/composer/installed.json
r3724500 r3761091 3 3 { 4 4 "name": "alanef/free_plugin_lib", 5 "version": "1.3. 0",6 "version_normalized": "1.3. 0.0",5 "version": "1.3.2", 6 "version_normalized": "1.3.2.0", 7 7 "source": { 8 8 "type": "git", 9 9 "url": "https://github.com/alanef/free_plugin_lib.git", 10 "reference": " 6dfce2995dde31a1d12e6f8113c4b420ebd83fe9"10 "reference": "9e94ffc83b7ec4cb82ce341cfc7771fc3af0146a" 11 11 }, 12 12 "dist": { 13 13 "type": "zip", 14 "url": "https://api.github.com/repos/alanef/free_plugin_lib/zipball/ 6dfce2995dde31a1d12e6f8113c4b420ebd83fe9",15 "reference": " 6dfce2995dde31a1d12e6f8113c4b420ebd83fe9",14 "url": "https://api.github.com/repos/alanef/free_plugin_lib/zipball/9e94ffc83b7ec4cb82ce341cfc7771fc3af0146a", 15 "reference": "9e94ffc83b7ec4cb82ce341cfc7771fc3af0146a", 16 16 "shasum": "" 17 17 }, … … 25 25 "yoast/wp-test-utils": "^1.2" 26 26 }, 27 "time": "2026-10- 02T09:11:20+00:00",27 "time": "2026-10-23T06:44:46+00:00", 28 28 "type": "library", 29 29 "installation-source": "dist", … … 46 46 "support": { 47 47 "issues": "https://github.com/alanef/free_plugin_lib/issues", 48 "source": "https://github.com/alanef/free_plugin_lib/tree/v1.3. 0"48 "source": "https://github.com/alanef/free_plugin_lib/tree/v1.3.2" 49 49 }, 50 50 "install-path": "../alanef/free_plugin_lib" -
stop-user-enumeration/tags/1.7.10/includes/vendor/composer/installed.php
r3724500 r3761091 2 2 'root' => array( 3 3 'name' => 'fullworks/stop-user-enumeration', 4 'pretty_version' => 'v1.7. 9',5 'version' => '1.7. 9.0',6 'reference' => ' a87eb0b6cac8051b239c5ad7294599b74bdbe768',4 'pretty_version' => 'v1.7.10', 5 'version' => '1.7.10.0', 6 'reference' => 'eb7d4253c3576c49fdff00384dbac79813ec744a', 7 7 'type' => 'wordpress-plugin', 8 8 'install_path' => __DIR__ . '/../../../', … … 12 12 'versions' => array( 13 13 'alanef/free_plugin_lib' => array( 14 'pretty_version' => '1.3. 0',15 'version' => '1.3. 0.0',16 'reference' => ' 6dfce2995dde31a1d12e6f8113c4b420ebd83fe9',14 'pretty_version' => '1.3.2', 15 'version' => '1.3.2.0', 16 'reference' => '9e94ffc83b7ec4cb82ce341cfc7771fc3af0146a', 17 17 'type' => 'library', 18 18 'install_path' => __DIR__ . '/../alanef/free_plugin_lib', … … 30 30 ), 31 31 'fullworks/stop-user-enumeration' => array( 32 'pretty_version' => 'v1.7. 9',33 'version' => '1.7. 9.0',34 'reference' => ' a87eb0b6cac8051b239c5ad7294599b74bdbe768',32 'pretty_version' => 'v1.7.10', 33 'version' => '1.7.10.0', 34 'reference' => 'eb7d4253c3576c49fdff00384dbac79813ec744a', 35 35 'type' => 'wordpress-plugin', 36 36 'install_path' => __DIR__ . '/../../../', -
stop-user-enumeration/tags/1.7.10/languages/stop-user-enumeration.pot
r3724500 r3761091 3 3 msgid "" 4 4 msgstr "" 5 "Project-Id-Version: Stop User Enumeration 1.7. 9\n"5 "Project-Id-Version: Stop User Enumeration 1.7.10\n" 6 6 "Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/stop-user-enumeration\n" 7 7 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" -
stop-user-enumeration/tags/1.7.10/readme.txt
r3724500 r3761091 6 6 Tested up to: 7.1 7 7 Requires PHP: 7.4 8 Stable tag: 1.7.9 8 Stable tag: 1.7.10 9 Type: free 9 10 License: GPLv2 or later 10 11 License URI: http://www.gnu.org/licenses/gpl-2.0.html -
stop-user-enumeration/tags/1.7.10/stop-user-enumeration.php
r3724500 r3761091 4 4 Plugin URI: https://fullworksplugins.com/products/stop-user-enumeration/ 5 5 Description: Helps secure your site against hacking attacks through detecting User Enumeration 6 Version: 1.7. 96 Version: 1.7.10 7 7 Author: Fullworks 8 8 Requires at least: 6.3 … … 43 43 44 44 // Define the plugin version constant. 45 define( 'STOP_USER_ENUMERATION_PLUGIN_VERSION', '1.7. 9' );45 define( 'STOP_USER_ENUMERATION_PLUGIN_VERSION', '1.7.10' ); 46 46 47 47 // Include the autoloader to dynamically include the classes. -
stop-user-enumeration/trunk/changelog.txt
r3724500 r3761091 1 1 == Changelog == 2 = 1.7.10 = 3 * Fixed: the settings notice could not be dismissed and kept coming back on every page load 4 * Fixed: on sites running other Fullworks free plugins, the opt-in notice and menu could belong to the wrong plugin 5 * Fixed: leaving the opt-in screen without choosing left the notice up for good; visiting settings now shows the opt-in screen again until you click Allow or Skip 6 * Changed: the notice now links straight to the opt-in screen instead of the settings page 7 * Changed: updated the bundled opt-in library to 1.3.2 8 2 9 = 1.7.9 = 3 10 * Fixed two database writes on every page load: the plugin and its bundled opt-in library both registered an uninstall hook and overwrote each other's entry in the uninstall_plugins option. Uninstall now runs from uninstall.php instead -
stop-user-enumeration/trunk/includes/vendor/alanef/free_plugin_lib/src/Assets/scripts/main.js
r3259418 r3761091 29 29 action: 'ffpl_handle_optin', 30 30 email: email, 31 shortname: ffplData.shortname, 31 32 nonce: ffplData.nonce 32 33 }, -
stop-user-enumeration/trunk/includes/vendor/alanef/free_plugin_lib/src/Classes/Email.php
r3679961 r3761091 4 4 5 5 class Email { 6 private static$plugin_shortname;6 private $plugin_shortname; 7 7 8 8 // Plugin shortname to ID mapping … … 20 20 21 21 public function __construct($plugin_shortname) { 22 self::$plugin_shortname = $plugin_shortname;22 $this->plugin_shortname = $plugin_shortname; 23 23 } 24 24 … … 33 33 34 34 // Get plugin ID from map 35 $plugin_id = $plugin_map[ self::$plugin_shortname] ?? null;35 $plugin_id = $plugin_map[$this->plugin_shortname] ?? null; 36 36 if (!$plugin_id) { 37 37 return false; -
stop-user-enumeration/trunk/includes/vendor/alanef/free_plugin_lib/src/Main.php
r3724500 r3761091 7 7 class Main { 8 8 /** 9 * Shortname of the most recently constructed instance, used only as the default for 10 * plugin_uninstall(). Every plugin bundling this library shares one copy of the class, 11 * so per-plugin state must live on the instance, never here. 12 * 9 13 * @var mixed 10 14 */ 11 private static $plugin_shortname; 15 private static $last_plugin_shortname; 16 /** 17 * @var mixed 18 */ 19 private $plugin_shortname; 12 20 /** 13 21 * @var string 14 22 */ 15 private static $version = '1.3.0'; 16 /** 23 private static $version = '1.3.2'; 24 /** 25 * The host plugin's settings page as passed: a menu slug ('stop-user-enumeration'), a hook 26 * suffix ('settings_page_contact-form-settings') or '' for a plugin with no settings page. 27 * 17 28 * @var mixed 18 29 */ 19 30 private $page; 31 /** 32 * The menu slug part of $page, compared with $_GET['page']. 33 * 34 * @var string 35 */ 36 private $page_slug; 20 37 /** 21 38 * @var \WP_Screen|null … … 33 50 34 51 public function __construct($plugin_file, $settings_page, $plugin_shortname, $page, $plugin_name) { 35 self::$plugin_shortname = $plugin_shortname; 52 $this->plugin_shortname = $plugin_shortname; 53 self::$last_plugin_shortname = $plugin_shortname; 36 54 $this->page = $page; 55 $this->page_slug = (string) preg_replace('/^.*_page_/', '', (string) $page); 37 56 $this->plugin_file = $plugin_file; 38 57 $this->settings_page = $settings_page; … … 67 86 */ 68 87 public static function plugin_uninstall($plugin_shortname = null) { 69 $plugin_shortname = null === $plugin_shortname ? self::$ plugin_shortname : $plugin_shortname;88 $plugin_shortname = null === $plugin_shortname ? self::$last_plugin_shortname : $plugin_shortname; 70 89 if (empty($plugin_shortname)) { 71 90 return; … … 81 100 // Verify nonce - the nonce IS the ffpl_skip value 82 101 $nonce = sanitize_text_field(wp_unslash($_GET['ffpl_skip'])); 83 if (!wp_verify_nonce($nonce, 'ffpl_skip_' . self::$plugin_shortname)) {102 if (!wp_verify_nonce($nonce, 'ffpl_skip_' . $this->plugin_shortname)) { 84 103 return; 85 104 } 86 105 87 106 // Set status to optout - user explicitly skipped 88 update_site_option( self::$plugin_shortname . '_form_rendered', 'optout');107 update_site_option($this->plugin_shortname . '_form_rendered', 'optout'); 89 108 90 109 // Redirect to clean URL (remove the skip param) … … 94 113 95 114 public function handle_optin_page() { 115 // admin_init also runs for admin-ajax.php, and a redirect there breaks every AJAX call on the site 116 if (wp_doing_ajax() || '' === $this->page_slug || !current_user_can('manage_options')) { 117 return; 118 } 119 96 120 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- This is page routing, not form processing 97 121 $current_page = isset($_GET['page']) ? sanitize_text_field(wp_unslash($_GET['page'])) : ''; 98 $option = get_site_option(self::$plugin_shortname . '_form_rendered'); 99 if ('pending' === $option && $current_page === $this->page) { 100 update_site_option(self::$plugin_shortname . '_form_rendered', 'rendering'); 101 wp_safe_redirect(admin_url('options-general.php?page=ffpl-opt-in-' . self::$plugin_shortname)); 122 $option = get_site_option($this->plugin_shortname . '_form_rendered'); 123 // 'rendering' means the opt-in screen was shown but left without a choice, so ask again 124 if (in_array($option, array('pending', 'rendering'), true) && $current_page === $this->page_slug) { 125 update_site_option($this->plugin_shortname . '_form_rendered', 'rendering'); 126 wp_safe_redirect(admin_url('options-general.php?page=ffpl-opt-in-' . $this->plugin_shortname)); 102 127 exit; 103 128 } … … 110 135 $settings_link 111 136 ); 112 if ('optout' === get_site_option( self::$plugin_shortname . '_form_rendered', 'optout')) {113 $settings_link = '<a href="' . esc_url(admin_url('options-general.php?page=ffpl-opt-in-'. self::$plugin_shortname )) . '" style="font-weight:900; font-size: 110%; color: #b32d2e;">' . esc_html($this->translate('Opt In')) . '</a>';137 if ('optout' === get_site_option($this->plugin_shortname . '_form_rendered', 'optout')) { 138 $settings_link = '<a href="' . esc_url(admin_url('options-general.php?page=ffpl-opt-in-'.$this->plugin_shortname )) . '" style="font-weight:900; font-size: 110%; color: #b32d2e;">' . esc_html($this->translate('Opt In')) . '</a>'; 114 139 array_unshift( 115 140 $links, … … 123 148 public function add_settings_page() { 124 149 // First-run detection - if option doesn't exist, set to pending 125 $option = get_site_option( self::$plugin_shortname . '_form_rendered');150 $option = get_site_option($this->plugin_shortname . '_form_rendered'); 126 151 if (false === $option) { 127 update_site_option( self::$plugin_shortname . '_form_rendered', 'pending');152 update_site_option($this->plugin_shortname . '_form_rendered', 'pending'); 128 153 $option = 'pending'; 129 154 } … … 135 160 esc_html($this->translate('Opt In ') . esc_html( $this->plugin_name) ), // Menu title 136 161 'manage_options', // Capability 137 'ffpl-opt-in-'. self::$plugin_shortname, // Menu slug162 'ffpl-opt-in-'.$this->plugin_shortname, // Menu slug 138 163 array($this, 'render_opt_in_page') // Callback function 139 164 ); … … 200 225 </div> 201 226 <div class="button-2"> 202 <a href="<?php echo esc_url(add_query_arg('ffpl_skip', wp_create_nonce('ffpl_skip_' . self::$plugin_shortname), $this->settings_page)); ?>"227 <a href="<?php echo esc_url(add_query_arg('ffpl_skip', wp_create_nonce('ffpl_skip_' . $this->plugin_shortname), $this->settings_page)); ?>" 203 228 class="button button-secondary btn-skip" name="action" value="skip" 204 229 tabindex="2"> … … 241 266 public function conditional_enqueue_assets($hook) { 242 267 // Only load on our specific page 243 if ($hook !== 'settings_page_ffpl-opt-in-'. self::$plugin_shortname) {268 if ($hook !== 'settings_page_ffpl-opt-in-'.$this->plugin_shortname) { 244 269 return; 245 270 } … … 260 285 'ajaxurl' => admin_url('admin-ajax.php'), 261 286 'nonce' => wp_create_nonce('ffpl_optin_nonce'), 287 'shortname' => $this->plugin_shortname, 262 288 'settings_page' => $this->settings_page 263 289 )); … … 265 291 266 292 public function handle_optin_ajax() { 293 // Every plugin bundling the library registers this handler; leave other plugins' requests to them 294 if (isset($_POST['shortname']) && !$this->is_own_shortname(sanitize_key(wp_unslash($_POST['shortname'])))) { 295 return; 296 } 297 267 298 // Verify request method 268 299 if (!isset($_SERVER['REQUEST_METHOD']) || $_SERVER['REQUEST_METHOD'] !== 'POST') { … … 297 328 $email = isset($_POST['email']) ? sanitize_email(wp_unslash($_POST['email'])) : ''; 298 329 299 $email_handler = new Email( self::$plugin_shortname);330 $email_handler = new Email($this->plugin_shortname); 300 331 $result = $email_handler->handle_optin_submission($email); 301 332 302 333 if ($result) { 303 update_site_option( self::$plugin_shortname . '_form_rendered', 'optin');334 update_site_option($this->plugin_shortname . '_form_rendered', 'optin'); 304 335 wp_send_json_success(array( 305 336 'redirect_url' => $this->settings_page 306 337 )); 307 338 } else { 308 update_site_option( self::$plugin_shortname . '_form_rendered', 'optout');339 update_site_option($this->plugin_shortname . '_form_rendered', 'optout'); 309 340 wp_send_json_success(array( 310 341 'redirect_url' => $this->settings_page … … 325 356 } 326 357 327 $option = get_site_option( self::$plugin_shortname . '_form_rendered');358 $option = get_site_option($this->plugin_shortname . '_form_rendered'); 328 359 329 360 // Only show notice if no decision has been made yet (pending or rendering) … … 334 365 335 366 // Don't show if user dismissed the notice 336 if (get_user_meta(get_current_user_id(), self::$plugin_shortname . '_notice_dismissed', true)) {367 if (get_user_meta(get_current_user_id(), $this->plugin_shortname . '_notice_dismissed', true)) { 337 368 return; 338 369 } … … 345 376 'tools', 346 377 'options-general', 347 'settings_page_' . $this->page,348 378 ); 379 if ('' !== $this->page_slug) { 380 // A hook suffix is already the screen base; a menu slug is assumed to be under Settings 381 $display_on_pages[] = $this->page === $this->page_slug ? 'settings_page_' . $this->page : $this->page; 382 } 349 383 350 384 if (!in_array($page, $display_on_pages, true)) { … … 352 386 } 353 387 354 $opt_in_url = admin_url('options-general.php?page=ffpl-opt-in-' . self::$plugin_shortname);388 $opt_in_url = admin_url('options-general.php?page=ffpl-opt-in-' . $this->plugin_shortname); 355 389 ?> 356 <div class="notice notice-info is-dismissible ffpl-setup-notice" data-shortname="<?php echo esc_attr( self::$plugin_shortname); ?>">390 <div class="notice notice-info is-dismissible ffpl-setup-notice" data-shortname="<?php echo esc_attr($this->plugin_shortname); ?>"> 357 391 <p> 358 392 <strong><?php echo esc_html($this->plugin_name); ?>:</strong> 359 393 <?php 360 394 printf( 361 '%s <a href="%s"><strong>%s</strong></a> %s', 362 esc_html($this->translate('You haven\'t visited settings yet.')), 363 esc_url($this->settings_page), 364 esc_html($this->translate('Please check your settings')), 365 esc_html($this->translate('for optimal configuration and opt in for security updates, tips and occasional offers.')) 395 '%s <a href="%s"><strong>%s</strong></a>', 396 esc_html($this->translate('Choose whether to receive security updates, tips and occasional offers.')), 397 esc_url($opt_in_url), 398 esc_html($this->translate('Opt in or skip')) 366 399 ); 367 400 ?> … … 370 403 <script> 371 404 jQuery(document).ready(function($) { 372 $('.ffpl-setup-notice').on('click', '.notice-dismiss', function() { 373 var shortname = $(this).closest('.ffpl-setup-notice').data('shortname'); 405 $('.ffpl-setup-notice[data-shortname="<?php echo esc_js($this->plugin_shortname); ?>"]').on('click', '.notice-dismiss', function() { 374 406 $.post(ajaxurl, { 375 407 action: 'ffpl_dismiss_notice', 376 shortname: shortname,408 shortname: '<?php echo esc_js($this->plugin_shortname); ?>', 377 409 nonce: '<?php echo esc_js(wp_create_nonce('ffpl_dismiss_notice')); ?>' 378 410 }); … … 394 426 } 395 427 396 $shortname = isset($_POST['shortname']) ? sanitize_key($_POST['shortname']) : ''; 397 if ($shortname === self::$plugin_shortname) { 398 update_user_meta(get_current_user_id(), self::$plugin_shortname . '_notice_dismissed', true); 399 wp_send_json_success(); 400 } 401 402 wp_send_json_error(); 428 // Every plugin bundling the library registers this handler; leave other plugins' requests to them 429 $shortname = isset($_POST['shortname']) ? sanitize_key(wp_unslash($_POST['shortname'])) : ''; 430 if (!$this->is_own_shortname($shortname)) { 431 return; 432 } 433 434 // The meta key keeps the shortname's original case so existing dismissals stay readable 435 update_user_meta(get_current_user_id(), $this->plugin_shortname . '_notice_dismissed', true); 436 wp_send_json_success(); 403 437 wp_die(); 438 } 439 440 /** 441 * sanitize_key() lowercases, and host plugins pass mixed-case shortnames such as 'SUE'. 442 * 443 * @param string $shortname A shortname that has been through sanitize_key(). 444 */ 445 private function is_own_shortname($shortname) { 446 return '' !== $shortname && $shortname === sanitize_key($this->plugin_shortname); 404 447 } 405 448 -
stop-user-enumeration/trunk/includes/vendor/autoload.php
r3724500 r3761091 20 20 require_once __DIR__ . '/composer/autoload_real.php'; 21 21 22 return ComposerAutoloaderInit 09347b3d36fb9de9d34777796c5e08ee::getLoader();22 return ComposerAutoloaderInit3836c91313ab2ce66e7903b7eb493963::getLoader(); -
stop-user-enumeration/trunk/includes/vendor/composer/autoload_real.php
r3724500 r3761091 3 3 // autoload_real.php @generated by Composer 4 4 5 class ComposerAutoloaderInit 09347b3d36fb9de9d34777796c5e08ee5 class ComposerAutoloaderInit3836c91313ab2ce66e7903b7eb493963 6 6 { 7 7 private static $loader; … … 25 25 require __DIR__ . '/platform_check.php'; 26 26 27 spl_autoload_register(array('ComposerAutoloaderInit 09347b3d36fb9de9d34777796c5e08ee', 'loadClassLoader'), true, true);27 spl_autoload_register(array('ComposerAutoloaderInit3836c91313ab2ce66e7903b7eb493963', 'loadClassLoader'), true, true); 28 28 self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__)); 29 spl_autoload_unregister(array('ComposerAutoloaderInit 09347b3d36fb9de9d34777796c5e08ee', 'loadClassLoader'));29 spl_autoload_unregister(array('ComposerAutoloaderInit3836c91313ab2ce66e7903b7eb493963', 'loadClassLoader')); 30 30 31 31 require __DIR__ . '/autoload_static.php'; 32 call_user_func(\Composer\Autoload\ComposerStaticInit 09347b3d36fb9de9d34777796c5e08ee::getInitializer($loader));32 call_user_func(\Composer\Autoload\ComposerStaticInit3836c91313ab2ce66e7903b7eb493963::getInitializer($loader)); 33 33 34 34 $loader->register(true); -
stop-user-enumeration/trunk/includes/vendor/composer/autoload_static.php
r3724500 r3761091 5 5 namespace Composer\Autoload; 6 6 7 class ComposerStaticInit 09347b3d36fb9de9d34777796c5e08ee7 class ComposerStaticInit3836c91313ab2ce66e7903b7eb493963 8 8 { 9 9 public static $prefixLengthsPsr4 = array ( … … 88 88 { 89 89 return \Closure::bind(function () use ($loader) { 90 $loader->prefixLengthsPsr4 = ComposerStaticInit 09347b3d36fb9de9d34777796c5e08ee::$prefixLengthsPsr4;91 $loader->prefixDirsPsr4 = ComposerStaticInit 09347b3d36fb9de9d34777796c5e08ee::$prefixDirsPsr4;92 $loader->prefixesPsr0 = ComposerStaticInit 09347b3d36fb9de9d34777796c5e08ee::$prefixesPsr0;93 $loader->classMap = ComposerStaticInit 09347b3d36fb9de9d34777796c5e08ee::$classMap;90 $loader->prefixLengthsPsr4 = ComposerStaticInit3836c91313ab2ce66e7903b7eb493963::$prefixLengthsPsr4; 91 $loader->prefixDirsPsr4 = ComposerStaticInit3836c91313ab2ce66e7903b7eb493963::$prefixDirsPsr4; 92 $loader->prefixesPsr0 = ComposerStaticInit3836c91313ab2ce66e7903b7eb493963::$prefixesPsr0; 93 $loader->classMap = ComposerStaticInit3836c91313ab2ce66e7903b7eb493963::$classMap; 94 94 95 95 }, null, ClassLoader::class); -
stop-user-enumeration/trunk/includes/vendor/composer/installed.json
r3724500 r3761091 3 3 { 4 4 "name": "alanef/free_plugin_lib", 5 "version": "1.3. 0",6 "version_normalized": "1.3. 0.0",5 "version": "1.3.2", 6 "version_normalized": "1.3.2.0", 7 7 "source": { 8 8 "type": "git", 9 9 "url": "https://github.com/alanef/free_plugin_lib.git", 10 "reference": " 6dfce2995dde31a1d12e6f8113c4b420ebd83fe9"10 "reference": "9e94ffc83b7ec4cb82ce341cfc7771fc3af0146a" 11 11 }, 12 12 "dist": { 13 13 "type": "zip", 14 "url": "https://api.github.com/repos/alanef/free_plugin_lib/zipball/ 6dfce2995dde31a1d12e6f8113c4b420ebd83fe9",15 "reference": " 6dfce2995dde31a1d12e6f8113c4b420ebd83fe9",14 "url": "https://api.github.com/repos/alanef/free_plugin_lib/zipball/9e94ffc83b7ec4cb82ce341cfc7771fc3af0146a", 15 "reference": "9e94ffc83b7ec4cb82ce341cfc7771fc3af0146a", 16 16 "shasum": "" 17 17 }, … … 25 25 "yoast/wp-test-utils": "^1.2" 26 26 }, 27 "time": "2026-10- 02T09:11:20+00:00",27 "time": "2026-10-23T06:44:46+00:00", 28 28 "type": "library", 29 29 "installation-source": "dist", … … 46 46 "support": { 47 47 "issues": "https://github.com/alanef/free_plugin_lib/issues", 48 "source": "https://github.com/alanef/free_plugin_lib/tree/v1.3. 0"48 "source": "https://github.com/alanef/free_plugin_lib/tree/v1.3.2" 49 49 }, 50 50 "install-path": "../alanef/free_plugin_lib" -
stop-user-enumeration/trunk/includes/vendor/composer/installed.php
r3724500 r3761091 2 2 'root' => array( 3 3 'name' => 'fullworks/stop-user-enumeration', 4 'pretty_version' => 'v1.7. 9',5 'version' => '1.7. 9.0',6 'reference' => ' a87eb0b6cac8051b239c5ad7294599b74bdbe768',4 'pretty_version' => 'v1.7.10', 5 'version' => '1.7.10.0', 6 'reference' => 'eb7d4253c3576c49fdff00384dbac79813ec744a', 7 7 'type' => 'wordpress-plugin', 8 8 'install_path' => __DIR__ . '/../../../', … … 12 12 'versions' => array( 13 13 'alanef/free_plugin_lib' => array( 14 'pretty_version' => '1.3. 0',15 'version' => '1.3. 0.0',16 'reference' => ' 6dfce2995dde31a1d12e6f8113c4b420ebd83fe9',14 'pretty_version' => '1.3.2', 15 'version' => '1.3.2.0', 16 'reference' => '9e94ffc83b7ec4cb82ce341cfc7771fc3af0146a', 17 17 'type' => 'library', 18 18 'install_path' => __DIR__ . '/../alanef/free_plugin_lib', … … 30 30 ), 31 31 'fullworks/stop-user-enumeration' => array( 32 'pretty_version' => 'v1.7. 9',33 'version' => '1.7. 9.0',34 'reference' => ' a87eb0b6cac8051b239c5ad7294599b74bdbe768',32 'pretty_version' => 'v1.7.10', 33 'version' => '1.7.10.0', 34 'reference' => 'eb7d4253c3576c49fdff00384dbac79813ec744a', 35 35 'type' => 'wordpress-plugin', 36 36 'install_path' => __DIR__ . '/../../../', -
stop-user-enumeration/trunk/languages/stop-user-enumeration.pot
r3724500 r3761091 3 3 msgid "" 4 4 msgstr "" 5 "Project-Id-Version: Stop User Enumeration 1.7. 9\n"5 "Project-Id-Version: Stop User Enumeration 1.7.10\n" 6 6 "Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/stop-user-enumeration\n" 7 7 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" -
stop-user-enumeration/trunk/readme.txt
r3724500 r3761091 6 6 Tested up to: 7.1 7 7 Requires PHP: 7.4 8 Stable tag: 1.7.9 8 Stable tag: 1.7.10 9 Type: free 9 10 License: GPLv2 or later 10 11 License URI: http://www.gnu.org/licenses/gpl-2.0.html -
stop-user-enumeration/trunk/stop-user-enumeration.php
r3724500 r3761091 4 4 Plugin URI: https://fullworksplugins.com/products/stop-user-enumeration/ 5 5 Description: Helps secure your site against hacking attacks through detecting User Enumeration 6 Version: 1.7. 96 Version: 1.7.10 7 7 Author: Fullworks 8 8 Requires at least: 6.3 … … 43 43 44 44 // Define the plugin version constant. 45 define( 'STOP_USER_ENUMERATION_PLUGIN_VERSION', '1.7. 9' );45 define( 'STOP_USER_ENUMERATION_PLUGIN_VERSION', '1.7.10' ); 46 46 47 47 // Include the autoloader to dynamically include the classes.
Note:
See TracChangeset
for help on using the changeset viewer.
![(please configure the [header_logo] section in trac.ini)](/chrome/site/your_project_logo.png)