WP fail2ban - Version 4.4.0.8

Version Description

  • Backport fix for mu-plugins activation.
  • Update Freemius library.
Download this release

Release Info

Developer invisnet
Plugin Icon 128x128 WP fail2ban
Version 4.4.0.8
Comparing to
See all releases

Code changes from version 4.4.0.6 to 4.4.0.8

Files changed (41) hide show
  1. admin/admin.php +27 -2
  2. admin/css/admin.css +1 -1
  3. constants.php +1 -1
  4. filters.d/wordpress-extra.conf +3 -3
  5. filters.d/wordpress-hard.conf +5 -5
  6. filters.d/wordpress-soft.conf +1 -1
  7. functions.php +1 -0
  8. init.php +5 -0
  9. lib/activation.php +1 -0
  10. lib/site-health.php +82 -0
  11. readme.txt +46 -37
  12. vendor/freemius/wordpress-sdk/includes/class-freemius.php +318 -135
  13. vendor/freemius/wordpress-sdk/includes/class-fs-logger.php +2 -1
  14. vendor/freemius/wordpress-sdk/includes/entities/class-fs-site.php +1 -5
  15. vendor/freemius/wordpress-sdk/includes/fs-essential-functions.php +7 -19
  16. vendor/freemius/wordpress-sdk/includes/managers/class-fs-clone-manager.php +175 -68
  17. vendor/freemius/wordpress-sdk/includes/managers/class-fs-option-manager.php +25 -76
  18. vendor/freemius/wordpress-sdk/includes/sdk/FreemiusWordPress.php +3 -1
  19. vendor/freemius/wordpress-sdk/start.php +6 -2
  20. vendor/freemius/wordpress-sdk/templates/account.php +27 -21
  21. vendor/freemius/wordpress-sdk/templates/account/billing.php +1 -1
  22. vendor/freemius/wordpress-sdk/templates/account/partials/disconnect-button.php +104 -0
  23. vendor/freemius/wordpress-sdk/templates/auto-installation.php +1 -1
  24. vendor/freemius/wordpress-sdk/templates/connect.php +4 -5
  25. vendor/freemius/wordpress-sdk/templates/contact.php +1 -1
  26. vendor/freemius/wordpress-sdk/templates/debug.php +8 -4
  27. vendor/freemius/wordpress-sdk/templates/firewall-issues-js.php +1 -2
  28. vendor/freemius/wordpress-sdk/templates/forms/affiliation.php +2 -2
  29. vendor/freemius/wordpress-sdk/templates/forms/data-debug-mode.php +1 -1
  30. vendor/freemius/wordpress-sdk/templates/forms/deactivation/form.php +7 -7
  31. vendor/freemius/wordpress-sdk/templates/forms/email-address-update.php +1 -1
  32. vendor/freemius/wordpress-sdk/templates/forms/license-activation.php +3 -4
  33. vendor/freemius/wordpress-sdk/templates/forms/optout.php +2 -2
  34. vendor/freemius/wordpress-sdk/templates/forms/resend-key.php +1 -1
  35. vendor/freemius/wordpress-sdk/templates/forms/trial-start.php +1 -1
  36. vendor/freemius/wordpress-sdk/templates/forms/user-change.php +1 -1
  37. vendor/freemius/wordpress-sdk/templates/gdpr-optin-js.php +1 -1
  38. vendor/freemius/wordpress-sdk/templates/partials/network-activation.php +1 -1
  39. vendor/freemius/wordpress-sdk/templates/sticky-admin-notice-js.php +1 -2
  40. vendor/freemius/wordpress-sdk/templates/tabs-capture-js.php +1 -1
  41. wp-fail2ban.php +1 -1
admin/admin.php CHANGED
@@ -300,6 +300,7 @@ function admin_menu_fix(): void
300
  /**
301
  * Add Settings link on Plugins page
302
  *
 
303
  * @since 4.4.0.3 Allow $plugin_data to be null despite spec
304
  * @since 4.4.0 Add type hints, return type
305
  * @since 4.2.0
@@ -320,6 +321,29 @@ function plugin_action_links(array $actions, string $plugin_file, ?array $plugin
320
  if (preg_match("|$plugin_file\$|", WP_FAIL2BAN_FILE) &&
321
  (!is_multisite() || is_network_admin()))
322
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
323
  // No settings tabs for ClassicPress + Free
324
  if (function_exists('\add_security_page') &&
325
  !wf_fs()->can_use_premium_code())
@@ -327,9 +351,10 @@ function plugin_action_links(array $actions, string $plugin_file, ?array $plugin
327
  return $actions;
328
  }
329
 
330
- if (!wf_fs()->can_use_premium_code() ||
 
331
  ((is_multisite() && wf_fs()->is_plan_or_trial('silver')) ||
332
- (!is_multisite() && wf_fs()->is_plan_or_trial('bronze'))))
333
  {
334
  $settings = sprintf(
335
  '<a href="%s?page=wpf2b-settings&tab=about" title="%s">%s</a>',
300
  /**
301
  * Add Settings link on Plugins page
302
  *
303
+ * @since 4.4.0.8 Activate "normal" plugin if running as MU
304
  * @since 4.4.0.3 Allow $plugin_data to be null despite spec
305
  * @since 4.4.0 Add type hints, return type
306
  * @since 4.2.0
321
  if (preg_match("|$plugin_file\$|", WP_FAIL2BAN_FILE) &&
322
  (!is_multisite() || is_network_admin()))
323
  {
324
+ foreach (get_mu_plugins() as $plugin => $data) {
325
+ if (0 === strpos($data['Name'], 'WP fail2ban')) {
326
+ // MU plugin
327
+ //
328
+ // * Make sure the "normal" plugin is activated
329
+ // * Remove "Deactivate" and "Delete" links
330
+ $plugin = plugin_basename(WP_FAIL2BAN_FILE);
331
+
332
+ if (array_key_exists($plugin, get_plugins()) && !is_plugin_active($plugin)) {
333
+ activate_plugin(
334
+ $plugin,
335
+ '', // don't redirect anywhere
336
+ false,
337
+ true // don't call activation hooks
338
+ );
339
+ }
340
+
341
+ unset($actions['deactivate']);
342
+ unset($actions['delete']);
343
+ break;
344
+ }
345
+ }
346
+
347
  // No settings tabs for ClassicPress + Free
348
  if (function_exists('\add_security_page') &&
349
  !wf_fs()->can_use_premium_code())
351
  return $actions;
352
  }
353
 
354
+ if (!wf_fs()->is_activation_mode() &&
355
+ (!wf_fs()->can_use_premium_code() ||
356
  ((is_multisite() && wf_fs()->is_plan_or_trial('silver')) ||
357
+ (!is_multisite() && wf_fs()->is_plan_or_trial('bronze')))))
358
  {
359
  $settings = sprintf(
360
  '<a href="%s?page=wpf2b-settings&tab=about" title="%s">%s</a>',
admin/css/admin.css CHANGED
@@ -1 +1 @@
1
- #wp-fail2ban,#wp-fail2ban *,#wp-fail2ban ::after,#wp-fail2ban ::before{box-sizing:border-box}@font-face{font-family:'WPf2b';font-style:normal;font-weight:700;src:url(../../assets/WPf2b.woff2) format('woff2')}#wp-fail2ban #poststuff{max-width:960px}#wp-fail2ban #poststuff div.postbox h2{font-size:18px}#wp-fail2ban #poststuff div.postbox h3{font-size:16px;margin:0}#wp-fail2ban #poststuff div.postbox dl,#wp-fail2ban #poststuff div.postbox h3+ul{margin-top:.5em}#wp-fail2ban #poststuff div.postbox h4{font-size:14px;margin:0}#wp-fail2ban #poststuff div.postbox h6{font-size:13px;font-style:italic;font-weight:400;margin:0}#wp-fail2ban #poststuff div.postbox dl dt,div.help-tab-content dl dt{font-weight:700}#wp-fail2ban #poststuff div.postbox dl dd{margin-left:1em;padding-left:0}#wp-fail2ban #poststuff div.postbox dl dd p{margin:0 0 .5em}#wp-fail2ban #poststuff div.postbox dl dd ul li{margin-left:1em}#wp-fail2ban #poststuff div.postbox dl dd>ul{margin-top:0}#wp-fail2ban #poststuff div.postbox section.premium dl{padding-left:1em}#wp-fail2ban #poststuff div.postbox section a span.dashicons{text-decoration:none;vertical-align:sub}#wp-fail2ban #poststuff div.postbox section ul{list-style:disc;margin:0}#wp-fail2ban #poststuff div.postbox section ul li{margin-left:2em;margin-bottom:0}#wp-fail2ban #poststuff div.postbox section ul+h3{margin-top:1em}#wp-fail2ban #poststuff div.postbox section span.ht{font-style:italic}#wp-fail2ban #poststuff div.postbox section span.ht::before{content:'('}#wp-fail2ban #poststuff div.postbox section span.ht::after{content:')'}#wp-fail2ban #poststuff div.postbox.alt img{display:block;width:180px;height:auto;margin:20px auto 0;image-rendering:crisp-edges}#wp-fail2ban #poststuff div.postbox.alt h1{font-family:"WPf2b";font-weight:700;text-align:center}#wp-fail2ban #poststuff div.postbox.alt div.links{border-top:1px solid #ccc;margin-top:10px}#wp-fail2ban #poststuff div.postbox.alt div.links ul{text-align:center}#wp-fail2ban #poststuff div.postbox.alt div.links li{display:inline-block;padding:.5em 0}#wp-fail2ban #poststuff div.postbox.alt div.links li+li:before{content:'| ';padding:.5em .25em}div.help-tab-content dl dd p{margin:.5em 0}div.help-tab-content dl dd>p{margin-top:0}
1
+ #wp-fail2ban,#wp-fail2ban *,#wp-fail2ban ::after,#wp-fail2ban ::before{box-sizing:border-box}@font-face{font-family:"WPf2b";font-style:normal;font-weight:700;src:url(../../assets/WPf2b.woff2)format("woff2")}#wp-fail2ban #poststuff{max-width:960px}#wp-fail2ban #poststuff div.postbox h2{font-size:18px}#wp-fail2ban #poststuff div.postbox h3{font-size:16px;margin:0}#wp-fail2ban #poststuff div.postbox dl,#wp-fail2ban #poststuff div.postbox h3+ul{margin-top:.5em}#wp-fail2ban #poststuff div.postbox h4{font-size:14px;margin:0}#wp-fail2ban #poststuff div.postbox h6{font-size:13px;font-style:italic;font-weight:400;margin:0}#wp-fail2ban #poststuff div.postbox dl dt,div.help-tab-content dl dt{font-weight:700}#wp-fail2ban #poststuff div.postbox dl dd{margin-left:1em;padding-left:0}#wp-fail2ban #poststuff div.postbox dl dd p{margin:0 0 .5em}#wp-fail2ban #poststuff div.postbox dl dd ul li{margin-left:1em}#wp-fail2ban #poststuff div.postbox dl dd>ul{margin-top:0}#wp-fail2ban #poststuff div.postbox section.premium dl{padding-left:1em}#wp-fail2ban #poststuff div.postbox section a span.dashicons{text-decoration:none;vertical-align:sub}#wp-fail2ban #poststuff div.postbox section ul{list-style:disc;margin:0}#wp-fail2ban #poststuff div.postbox section ul li{margin-left:2em;margin-bottom:0}#wp-fail2ban #poststuff div.postbox section ul+h3{margin-top:1em}#wp-fail2ban #poststuff div.postbox section span.ht{font-style:italic}#wp-fail2ban #poststuff div.postbox section span.ht::before{content:"("}#wp-fail2ban #poststuff div.postbox section span.ht::after{content:")"}#wp-fail2ban #poststuff div.postbox.alt img{display:block;width:180px;height:auto;margin:20px auto 0;image-rendering:crisp-edges}#wp-fail2ban #poststuff div.postbox.alt h1{font-family:"WPf2b";font-weight:700;text-align:center}#wp-fail2ban #poststuff div.postbox.alt div.links{border-top:1px solid #ccc;margin-top:10px}#wp-fail2ban #poststuff div.postbox.alt div.links ul{text-align:center}#wp-fail2ban #poststuff div.postbox.alt div.links li{display:inline-block;padding:.5em 0}#wp-fail2ban #poststuff div.postbox.alt div.links li+li:before{content:"| ";padding:.5em .25em}div.help-tab-content dl dd p{margin:.5em 0}div.help-tab-content dl dd>p{margin-top:0}
constants.php CHANGED
@@ -12,7 +12,7 @@ namespace org\lecklider\charles\wordpress\wp_fail2ban;
12
  // @codeCoverageIgnoreStart
13
 
14
  if (!defined('WP_FAIL2BAN_VER')) {
15
- define('WP_FAIL2BAN_VER', '4.4.0.6');
16
  }
17
  if (!defined('WP_FAIL2BAN_VER_SHORT')) {
18
  define('WP_FAIL2BAN_VER_SHORT', '4.4');
12
  // @codeCoverageIgnoreStart
13
 
14
  if (!defined('WP_FAIL2BAN_VER')) {
15
+ define('WP_FAIL2BAN_VER', '4.4.0.8');
16
  }
17
  if (!defined('WP_FAIL2BAN_VER_SHORT')) {
18
  define('WP_FAIL2BAN_VER_SHORT', '4.4');
filters.d/wordpress-extra.conf CHANGED
@@ -1,5 +1,5 @@
1
  # Fail2Ban filter for extra failures
2
- # Auto-generated: 2022-07-15T16:27:21+00:00
3
  #
4
 
5
  [INCLUDES]
@@ -10,13 +10,13 @@ before = common.conf
10
 
11
  _daemon = (?:wordpress|wp)
12
 
13
- failregex = ^%(__prefix_line)sPassword reset requested for .* from <HOST>$
14
- ^%(__prefix_line)sComment \d+ from <HOST>$
15
  ^%(__prefix_line)sComment post not found \d+ from <HOST>$
16
  ^%(__prefix_line)sComments closed on post \d+ from <HOST>$
17
  ^%(__prefix_line)sComment attempt on trash post \d+ from <HOST>$
18
  ^%(__prefix_line)sComment attempt on draft post \d+ from <HOST>$
19
  ^%(__prefix_line)sComment attempt on password-protected post \d+ from <HOST>$
 
20
 
21
  ignoreregex =
22
 
1
  # Fail2Ban filter for extra failures
2
+ # Auto-generated: 2022-10-20T00:47:43+01:00
3
  #
4
 
5
  [INCLUDES]
10
 
11
  _daemon = (?:wordpress|wp)
12
 
13
+ failregex = ^%(__prefix_line)sComment \d+ from <HOST>$
 
14
  ^%(__prefix_line)sComment post not found \d+ from <HOST>$
15
  ^%(__prefix_line)sComments closed on post \d+ from <HOST>$
16
  ^%(__prefix_line)sComment attempt on trash post \d+ from <HOST>$
17
  ^%(__prefix_line)sComment attempt on draft post \d+ from <HOST>$
18
  ^%(__prefix_line)sComment attempt on password-protected post \d+ from <HOST>$
19
+ ^%(__prefix_line)sPassword reset requested for .* from <HOST>$
20
 
21
  ignoreregex =
22
 
filters.d/wordpress-hard.conf CHANGED
@@ -1,5 +1,5 @@
1
  # Fail2Ban filter for hard failures
2
- # Auto-generated: 2022-07-15T16:27:21+00:00
3
  #
4
 
5
  [INCLUDES]
@@ -11,18 +11,18 @@ before = common.conf
11
  _daemon = (?:wordpress|wp)
12
 
13
  failregex = ^%(__prefix_line)sImmediately block connections from <HOST>$
14
- ^%(__prefix_line)sSpam comment \d+ from <HOST>$
 
15
  ^%(__prefix_line)sBlocked user enumeration attempt from <HOST>$
16
  ^%(__prefix_line)sXML-RPC multicall authentication failure from <HOST>$
17
  ^%(__prefix_line)sPingback error .* generated from <HOST>$
18
- ^%(__prefix_line)sBlocked authentication attempt for .* from <HOST>$
19
- ^%(__prefix_line)sBlocked username authentication attempt for .* from <HOST>$
20
  ^%(__prefix_line)sAuthentication attempt for unknown user .* from <HOST>$
21
  ^%(__prefix_line)sREST authentication attempt for unknown user .* from <HOST>$
22
  ^%(__prefix_line)sXML-RPC authentication attempt for unknown user .* from <HOST>$
 
23
  ^%(__prefix_line)sXML-RPC request blocked from <HOST>$
24
  ^%(__prefix_line)s.*; Bogus Pingback from <HOST>$
25
- ^%(__prefix_line)sBlocked access from country '..' from <HOST>$
26
 
27
  ignoreregex =
28
 
1
  # Fail2Ban filter for hard failures
2
+ # Auto-generated: 2022-10-20T00:47:43+01:00
3
  #
4
 
5
  [INCLUDES]
11
  _daemon = (?:wordpress|wp)
12
 
13
  failregex = ^%(__prefix_line)sImmediately block connections from <HOST>$
14
+ ^%(__prefix_line)sBlocked authentication attempt for .* from <HOST>$
15
+ ^%(__prefix_line)sBlocked username authentication attempt for .* from <HOST>$
16
  ^%(__prefix_line)sBlocked user enumeration attempt from <HOST>$
17
  ^%(__prefix_line)sXML-RPC multicall authentication failure from <HOST>$
18
  ^%(__prefix_line)sPingback error .* generated from <HOST>$
19
+ ^%(__prefix_line)sSpam comment \d+ from <HOST>$
 
20
  ^%(__prefix_line)sAuthentication attempt for unknown user .* from <HOST>$
21
  ^%(__prefix_line)sREST authentication attempt for unknown user .* from <HOST>$
22
  ^%(__prefix_line)sXML-RPC authentication attempt for unknown user .* from <HOST>$
23
+ ^%(__prefix_line)sBlocked access from country '..' from <HOST>$
24
  ^%(__prefix_line)sXML-RPC request blocked from <HOST>$
25
  ^%(__prefix_line)s.*; Bogus Pingback from <HOST>$
 
26
 
27
  ignoreregex =
28
 
filters.d/wordpress-soft.conf CHANGED
@@ -1,5 +1,5 @@
1
  # Fail2Ban filter for soft failures
2
- # Auto-generated: 2022-07-15T16:27:21+00:00
3
  #
4
 
5
  [INCLUDES]
1
  # Fail2Ban filter for soft failures
2
+ # Auto-generated: 2022-10-20T00:47:43+01:00
3
  #
4
 
5
  [INCLUDES]
functions.php CHANGED
@@ -16,6 +16,7 @@ require_once __DIR__.'/lib/convert-data.php'; // @wpf2b exclude[lite]
16
  require_once __DIR__.'/lib/activation.php';
17
  require_once __DIR__.'/lib/compat.php';
18
  require_once __DIR__.'/lib/loader.php';
 
19
  require_once __DIR__.'/lib/syslog.php';
20
 
21
  require_once __DIR__.'/core.php';
16
  require_once __DIR__.'/lib/activation.php';
17
  require_once __DIR__.'/lib/compat.php';
18
  require_once __DIR__.'/lib/loader.php';
19
+ require_once __DIR__.'/lib/site-health.php';
20
  require_once __DIR__.'/lib/syslog.php';
21
 
22
  require_once __DIR__.'/core.php';
init.php CHANGED
@@ -189,6 +189,11 @@ function init(): void
189
  if (defined('WP_ADMIN') && WP_ADMIN) {
190
  require_once __DIR__.'/admin/admin.php'; // @codeCoverageIgnore
191
  }
 
 
 
 
 
192
  }
193
  add_action('init', __NAMESPACE__.'\init');
194
 
189
  if (defined('WP_ADMIN') && WP_ADMIN) {
190
  require_once __DIR__.'/admin/admin.php'; // @codeCoverageIgnore
191
  }
192
+
193
+ /**
194
+ * @since 4.4.0.8 Add our tests to Site Health
195
+ */
196
+ add_filter('site_status_tests', __NAMESPACE__.'\SiteHealth::get_tests');
197
  }
198
  add_action('init', __NAMESPACE__.'\init');
199
 
lib/activation.php CHANGED
@@ -28,6 +28,7 @@ defined('ABSPATH') or exit;
28
  HTML;
29
  } elseif (WP_FAIL2BAN_FILE == $path) {
30
  // OK, we're linking to ourself
 
31
  } else {
32
  $mu_file = str_replace('/', '/<wbr>', $mu_file);
33
  $mu_file = substr($mu_file, strlen(WPMU_PLUGIN_DIR)-1);
28
  HTML;
29
  } elseif (WP_FAIL2BAN_FILE == $path) {
30
  // OK, we're linking to ourself
31
+ break;
32
  } else {
33
  $mu_file = str_replace('/', '/<wbr>', $mu_file);
34
  $mu_file = substr($mu_file, strlen(WPMU_PLUGIN_DIR)-1);
lib/site-health.php ADDED
@@ -0,0 +1,82 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare(strict_types=1);
2
+ /**
3
+ * WP fail2ban Site Health
4
+ *
5
+ * @package wp-fail2ban
6
+ * @since 4.4.0.8
7
+ * @php 7.4
8
+ */
9
+ namespace org\lecklider\charles\wordpress\wp_fail2ban;
10
+
11
+ defined('ABSPATH') or exit;
12
+
13
+ class SiteHealth
14
+ {
15
+ protected static $instance = null;
16
+
17
+ /**
18
+ * Return an instance of the SiteHealth class, or create one if none exist yet.
19
+ *
20
+ * @since 4.4.0.8
21
+ *
22
+ * @return SiteHealth
23
+ */
24
+ public static function get_instance()
25
+ {
26
+ if (null === self::$instance) {
27
+ self::$instance = new SiteHealth();
28
+ }
29
+ return self::$instance;
30
+ }
31
+
32
+ /**
33
+ * @see \WP_Site_Health::get_tests()
34
+ *
35
+ * @since 4.4.0.8
36
+ *
37
+ * @return array The list of tests to run.
38
+ */
39
+ public static function get_tests(array $tests): array
40
+ {
41
+ $instance = self::get_instance();
42
+
43
+ $tests['direct']['wp_fail2ban_mu_ensure_active'] = [
44
+ 'label' => 'Ensure standard plugin activated when Must-Use',
45
+ 'test' => [$instance, 'get_test_mu_ensure_activated']
46
+ ];
47
+
48
+ return $tests;
49
+ }
50
+
51
+ /**
52
+ * Is the "normal" plugin activated if we're running as Must-Use?
53
+ *
54
+ * @since 4.4.0.8
55
+ *
56
+ * @return array Empty
57
+ */
58
+ public function get_test_mu_ensure_activated()
59
+ {
60
+ foreach (get_mu_plugins() as $plugin => $data) {
61
+ if (0 === strpos($data['Name'], 'WP fail2ban')) {
62
+ // MU plugin
63
+ //
64
+ // Make sure the "normal" plugin is activated, if installed that way
65
+ $plugin = plugin_basename(WP_FAIL2BAN_FILE);
66
+
67
+ if (array_key_exists($plugin, get_plugins()) && !is_plugin_active($plugin)) {
68
+ activate_plugin(
69
+ $plugin,
70
+ '', // don't redirect anywhere
71
+ false,
72
+ true // don't call activation hooks
73
+ );
74
+ }
75
+ break;
76
+ }
77
+ }
78
+
79
+ return [];
80
+ }
81
+ }
82
+
readme.txt CHANGED
@@ -4,8 +4,8 @@ Author URI: https://invis.net/?utm_source=wordpress.org&utm_medium=readme&utm_ca
4
  Plugin URI: https://wp-fail2ban.com/?utm_source=wordpress.org&utm_medium=readme&utm_campaign=wp-fail2ban-4.4.0
5
  Tags: fail2ban, login, security, syslog, brute force, protection, classicpress
6
  Requires at least: 4.2
7
- Tested up to: 6.0
8
- Stable tag: 4.4.0.6
9
  Requires PHP: 7.4
10
  License: GPLv3 or later
11
  License URI: http://www.gnu.org/licenses/gpl-3.0.html
@@ -25,55 +25,49 @@ Write a myriad of WordPress events to syslog for integration with fail2ban.
25
 
26
  = Features =
27
 
28
- * **Allow Pingbacks with XML-RPC Blocked** [Premium only]
29
- Pingbacks might be a relic of a bygone age, but they're still nice to have. *Wf2b* can now allow Pingsbacks while blocking other XML-RPC requests.
30
-
31
- * **Block XML-RPC Requests** [Premium only]
32
- Allow access for Jetpack and other trusted IPs while blocking everything else; introduces a new "hard" filter.
33
-
34
- * **Block Countries** [Premium only]
35
- Nothing but attacks from some countries? Block them!
36
-
37
- * **Multisite Support**
38
- Version 4.3 introduced [proper support for multisite networks](https://wp-fail2ban.com/features/multisite-networks/?utm_source=wordpress.org&utm_medium=readme&utm_campaign=wp-fail2ban-4.4.0).
39
 
40
  * **Block username logins**
41
- Sometimes it's not possible to block user enumeration (for example, if your theme provides Author profiles). Version 4.3 added support for requiring the use of email addresses for login.
42
-
43
- * **Filter for Empty Username Login Attempts**
44
- Some bots will try to login without a username. Version 4.3 logs these attempts and provides an "extra" filter to match them.
45
 
46
- * **syslog Dashboard Widget**
47
- Ever wondered what's being logged? The new dashboard widget shows the last 5 messages; the Premium version keeps a full history to help you analyse and prevent attacks.
 
48
 
49
- * **Support for 3rd-party Plugins**
50
- Version 4.2 introduced a simple API for authors to integrate their plugins with *WPf2b*, with 2 *experimental* add-ons:
51
- * [Contact Form 7](https://wordpress.org/plugins/wp-fail2ban-addon-contact-form-7/)
52
- * [Gravity Forms](https://wordpress.org/plugins/wp-fail2ban-addon-gravity-forms/)
53
 
54
- * **CloudFlare and Proxy Servers**
55
- *WPf2b* can be configured to work with [CloudFlare and other proxy servers](https://wp-fail2ban.com/features/cloudflare-and-proxy-servers/?utm_source=wordpress.org&utm_medium=readme&utm_campaign=wp-fail2ban-4.4.0).
56
 
57
- * **Comments**
58
- *WPf2b* can log comments (see [`WP_FAIL2BAN_LOG_COMMENTS`](https://docs.wp-fail2ban.com/en/4.4/defines.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=wp-fail2ban-4.4.0#wp-fail2ban-log-comments)) and attempted comments (see [`WP_FAIL2BAN_LOG_COMMENTS_EXTRA`](https://docs.wp-fail2ban.com/en/4.3/defines.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=wp-fail2ban-4.4.0#wp-fail2ban-log-comments-extra)).
59
 
60
  * **Pingbacks**
61
- *WPf2b* logs failed pingbacks, and can log all pingbacks. For an overview see [`WP_FAIL2BAN_LOG_PINGBACKS`](https://docs.wp-fail2ban.com/en/4.4/defines.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=wp-fail2ban-4.4.0#wp-fail2ban-log-pingbacks).
62
 
63
- * **Spam**
64
- *WPf2b* can log comments marked as spam. See [`WP_FAIL2BAN_LOG_SPAM`](https://docs.wp-fail2ban.com/en/4.4/defines.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=wp-fail2ban-4.4.0#wp-fail2ban-log-spam).
65
 
66
- * **Block User Enumeration**
67
- *WPf2b* can [block user enumeration](https://wp-fail2ban.com/features/block-user-enumeration/?utm_source=wordpress.org&utm_medium=readme&utm_campaign=wp-fail2ban-4.4.0).
68
 
69
- * **Work-Arounds for Broken syslogd**
70
- *WPf2b* can be configured to work around most syslogd weirdness. For an overview see [`WP_FAIL2BAN_SYSLOG_SHORT_TAG`](https://docs.wp-fail2ban.com/en/4.4/defines.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=wp-fail2ban-4.4.0#wp-fail2ban-syslog-short-tag) and [`WP_FAIL2BAN_HTTP_HOST`](https://docs.wp-fail2ban.com/en/4.3/defines.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=wp-fail2ban-4.4.0#wp-fail2ban-http-host).
 
71
 
72
- * **Blocking Users**
73
- *WPf2b* can be configured to short-cut the login process when the username matches a regex. For an overview see [`WP_FAIL2BAN_BLOCKED_USERS`](https://docs.wp-fail2ban.com/en/4.4/defines.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=wp-fail2ban-4.4.0#wp-fail2ban-blocked-users).
74
 
75
  * **`mu-plugins` Support**
76
- *WPf2b* can easily be configured as a must-use plugin - see [Configuration](https://docs.wp-fail2ban.com/en/4.4/configuration.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=wp-fail2ban-4.4.0#mu-plugins-support).
 
 
 
77
 
78
  == Installation ==
79
 
@@ -83,6 +77,15 @@ Write a myriad of WordPress events to syslog for integration with fail2ban.
83
 
84
  == Changelog ==
85
 
 
 
 
 
 
 
 
 
 
86
  = 4.4.0.6 =
87
  * Fix initialisation error in event log. [Premium only]
88
  * Fix type error in event log when no events available. [Premium only]
@@ -330,6 +333,12 @@ Write a myriad of WordPress events to syslog for integration with fail2ban.
330
 
331
  == Upgrade Notice ==
332
 
 
 
 
 
 
 
333
  = 4.4.0.6 =
334
  This is a bugfix release. You do not need to update your filters from 4.4.0.
335
 
4
  Plugin URI: https://wp-fail2ban.com/?utm_source=wordpress.org&utm_medium=readme&utm_campaign=wp-fail2ban-4.4.0
5
  Tags: fail2ban, login, security, syslog, brute force, protection, classicpress
6
  Requires at least: 4.2
7
+ Tested up to: 6.1
8
+ Stable tag: 4.4.0.8
9
  Requires PHP: 7.4
10
  License: GPLv3 or later
11
  License URI: http://www.gnu.org/licenses/gpl-3.0.html
25
 
26
  = Features =
27
 
28
+ * **Failed Login Attempts**
29
+ The very first feature of *WPf2b*: logging failed login attempts so the IP can be banned. Just as useful today as it was then.
30
+
31
+ * **Block User Enumeration**
32
+ One of the most common precursors to a password-guessing brute force attack is [user enumeration](https://wp-fail2ban.com/features/block-user-enumeration/?utm_source=wordpress.org&utm_medium=readme&utm_campaign=wp-fail2ban-4.4.0). *WPf2b* can block it, stopping the attack before it starts.
 
 
 
 
 
 
33
 
34
  * **Block username logins**
35
+ Sometimes it's not possible to block user enumeration (for example, if your theme provides Author profiles). *WPf2b* can require users to login with their email address instead of their username.
 
 
 
36
 
37
+ * **Blocking Users**
38
+ Anther of the older *WPf2b* features: the login process can be aborted for specified usernames.
39
+ Say a bot collected your site's usernames before you blocked user enumeration. Once you've changed all the usernames, add the old ones to the list; anything using them will trigger a "hard" fail.
40
 
41
+ * **Empty Username Login Attempts**
42
+ Some bots will try to login without a username; harmless, but annoying. These attempts are logged as a "soft" fail so the more persistent bots will be banned.
 
 
43
 
44
+ * **Spam**
45
+ *WPf2b* will log a spammer's IP address as a "hard" fail when their comment is marked as spam.
46
 
47
+ * **Attempted Comments**
48
+ Some spam bots try to comment on everything, even things that aren't there. *WPf2b* detects these and logs them as a "hard" fail.
49
 
50
  * **Pingbacks**
51
+ Pingbacks are a great feature, but they can be abused to attack the rest of the WWW. Rather than disable them completely, *WPf2b* effectively rate-limits potential attackers by logging the IP address as a "soft" fail.
52
 
53
+ * **Block XML-RPC Requests** [Premium]
54
+ The only reason most sites need XML-RPC (other than Pingbacks) is for Jetpack; *WPf2b* Premium can block XML-RPC while allowing Jetpack and/or Pingbacks.
55
 
56
+ * **Block Countries** [Premium]
57
+ Sometimes you just need a bigger hammer - if you're seeing nothing but attacks from some countries, block them!
58
 
59
+ * **Cloudflare and Proxy Servers**
60
+ *WPf2b* will work with [Cloudflare](https://wp-fail2ban.com/features/cloudflare-and-proxy-servers/?utm_source=wordpress.org&utm_medium=readme&utm_campaign=wp-fail2ban-4.4.0).
61
+ You can also configure your own list of trusted proxies.
62
 
63
+ * **syslog Dashboard Widget**
64
+ Ever wondered what's being logged? The dashboard widget shows the last 5 messages; the Premium version keeps a full history to help you analyse and prevent attacks.
65
 
66
  * **`mu-plugins` Support**
67
+ *WPf2b* can easily be configured as a "must-use plugin" - see [Configuration](https://docs.wp-fail2ban.com/en/4.4/configuration.html?utm_source=wordpress.org&utm_medium=readme&utm_campaign=wp-fail2ban-4.4.0#mu-plugins-support).
68
+
69
+ * **API to Extend *WPf2b***
70
+ If your plugin can detect behaviour which should be blocked, why reinvent the wheel?
71
 
72
  == Installation ==
73
 
77
 
78
  == Changelog ==
79
 
80
+ = 4.4.0.8 =
81
+ * Backport fix for `mu-plugins` activation.
82
+ * Update Freemius library.
83
+
84
+ = 4.4.0.7 =
85
+ * Backport fix for type error in menu-fixer when viewing Event Log (h/t @geniusmedia). [Premium only]
86
+ * Backport fixes for event summaries. [Premium only]
87
+ * Update Freemius library.
88
+
89
  = 4.4.0.6 =
90
  * Fix initialisation error in event log. [Premium only]
91
  * Fix type error in event log when no events available. [Premium only]
333
 
334
  == Upgrade Notice ==
335
 
336
+ = 4.4.0.8 =
337
+ This is a bugfix release. You do not need to update your filters from 4.4.0.
338
+
339
+ = 4.4.0.7 =
340
+ This is a Premium-only bugfix release. You do not need to update your filters from 4.4.0.
341
+
342
  = 4.4.0.6 =
343
  This is a bugfix release. You do not need to update your filters from 4.4.0.
344
 
vendor/freemius/wordpress-sdk/includes/class-freemius.php CHANGED
@@ -377,6 +377,8 @@
377
  const REASON_DIDNT_WORK_AS_EXPECTED = 14;
378
  const REASON_TEMPORARY_DEACTIVATION = 15;
379
 
 
 
380
  /**
381
  * @author Leo Fajardo (@leorw)
382
  * @since 2.3.1
@@ -392,7 +394,8 @@
392
  */
393
  private $_pricing_js_path = null;
394
 
395
- #endregion
 
396
 
397
  /* Ctor
398
  ------------------------------------------------------------------------------------------------------------------*/
@@ -1496,46 +1499,6 @@
1496
  }
1497
  }
1498
 
1499
- /**
1500
- * Add special parameter to WP admin AJAX calls so when we
1501
- * process AJAX calls we can identify its source properly.
1502
- *
1503
- * @author Leo Fajardo (@leorw)
1504
- * @since 2.0.0
1505
- */
1506
- static function _enrich_ajax_url() {
1507
- $admin_param = is_network_admin() ?
1508
- '_fs_network_admin' :
1509
- '_fs_blog_admin';
1510
- ?>
1511
- <script type="text/javascript">
1512
- (function ($) {
1513
- $(document).ajaxSend(function (event, jqxhr, settings) {
1514
- if (settings.url &&
1515
- -1 < settings.url.indexOf('admin-ajax.php') &&
1516
- ! ( settings.url.indexOf( '<?php echo $admin_param ?>' ) > 0 )
1517
- ) {
1518
- if (
1519
- 'string' === typeof settings.data &&
1520
- settings.data.indexOf( 'action=heartbeat' ) > 0
1521
- ) {
1522
- return;
1523
- }
1524
-
1525
- if (settings.url.indexOf('?') > 0) {
1526
- settings.url += '&';
1527
- } else {
1528
- settings.url += '?';
1529
- }
1530
-
1531
- settings.url += '<?php echo $admin_param ?>=true';
1532
- }
1533
- });
1534
- })(jQuery);
1535
- </script>
1536
- <?php
1537
- }
1538
-
1539
  /**
1540
  * Opens the support forum subemenu item in a new browser page.
1541
  *
@@ -3588,7 +3551,6 @@
3588
  $clone_manager = FS_Clone_Manager::instance();
3589
  add_action( 'init', array( $clone_manager, '_init' ) );
3590
 
3591
- add_action( 'admin_footer', array( 'Freemius', '_enrich_ajax_url' ) );
3592
  add_action( 'admin_footer', array( 'Freemius', '_open_support_forum_in_new_page' ) );
3593
 
3594
  if ( self::is_plugins_page() || self::is_themes_page() ) {
@@ -3635,10 +3597,58 @@
3635
  }
3636
 
3637
  return (
3638
- fs_strip_url_protocol( trailingslashit( $this->_site->url ) ) !== fs_strip_url_protocol( trailingslashit( get_site_url() ) )
3639
  );
3640
  }
3641
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3642
  /**
3643
  * @author Leo Fajardo (@leorw)
3644
  * @since 2.5.0
@@ -3665,7 +3675,7 @@
3665
  if (
3666
  is_object( $this->_license ) &&
3667
  ! $this->_license->is_utilized(
3668
- ( WP_FS__IS_LOCALHOST_FOR_SERVER || FS_Site::is_localhost_by_address( get_site_url() ) )
3669
  )
3670
  ) {
3671
  $license_key = $this->_license->secret_key;
@@ -4315,7 +4325,7 @@
4315
  $unique_id = self::$_accounts->get_option( 'unique_id', null, $blog_id );
4316
 
4317
  if ( empty( $unique_id ) || ! is_string( $unique_id ) ) {
4318
- $key = fs_strip_url_protocol( get_site_url( $blog_id ) );
4319
 
4320
  $secure_auth = defined( 'SECURE_AUTH_KEY' ) ? SECURE_AUTH_KEY : '';
4321
  if ( empty( $secure_auth ) ||
@@ -6669,6 +6679,18 @@
6669
  return $this->_storage->get( 'is_pending_activation', false );
6670
  }
6671
 
 
 
 
 
 
 
 
 
 
 
 
 
6672
  /**
6673
  * Check if plugin must be WordPress.org compliant.
6674
  *
@@ -6745,9 +6767,11 @@
6745
  private function get_cron_blog_id( $name ) {
6746
  $this->_logger->entrance( $name );
6747
 
6748
- /**
6749
- * @var object $cron_data
6750
- */
 
 
6751
  $cron_data = $this->get_cron_data( $name );
6752
 
6753
  return ( is_object( $cron_data ) && is_numeric( $cron_data->blog_id ) ) ?
@@ -6921,14 +6945,7 @@
6921
  return;
6922
  }
6923
 
6924
- /**
6925
- * @var object $cron_data
6926
- */
6927
- $cron_data = $this->get_cron_data( $name );
6928
-
6929
- $cron_blog_id = is_object( $cron_data ) && isset( $cron_data->blog_id ) ?
6930
- $cron_data->blog_id :
6931
- 0;
6932
 
6933
  $this->clear_cron_data( $name );
6934
 
@@ -6965,14 +6982,7 @@
6965
  return false;
6966
  }
6967
 
6968
- /**
6969
- * @var object $cron_data
6970
- */
6971
- $cron_data = $this->get_cron_data( $name );
6972
-
6973
- $cron_blog_id = is_object( $cron_data ) && isset( $cron_data->blog_id ) ?
6974
- $cron_data->blog_id :
6975
- 0;
6976
 
6977
  if ( 0 < $cron_blog_id ) {
6978
  switch_to_blog( $cron_blog_id );
@@ -7355,6 +7365,10 @@
7355
  * @param int $except_blog_id Since 2.0.0 when running in a multisite network environment, the cron execution is consolidated. This param allows excluding excluded specified blog ID from being the cron executor.
7356
  */
7357
  private function schedule_install_sync( $except_blog_id = 0 ) {
 
 
 
 
7358
  $this->schedule_cron( 'install_sync', 'install_sync', 'single', WP_FS__SCRIPT_START_TIME, false, $except_blog_id );
7359
  }
7360
 
@@ -7427,10 +7441,6 @@
7427
  * @param int|null $current_blog_id
7428
  */
7429
  function _sync_install_cron_method( array $blog_ids, $current_blog_id = null ) {
7430
- if ( $this->is_clone() ) {
7431
- return;
7432
- }
7433
-
7434
  if ( $this->is_registered() ) {
7435
  if ( 1 < count( $blog_ids ) ) {
7436
  $this->sync_installs( array(), true );
@@ -8072,6 +8082,10 @@
8072
  ( current_filter() !== ( 'activate_' . $this->_free_plugin_basename ) ) :
8073
  $this->is_premium();
8074
 
 
 
 
 
8075
  $this->_logger->info( 'Activating ' . ( $is_premium_version_activation ? 'premium' : 'free' ) . ' plugin version.' );
8076
 
8077
  if ( $this->is_plugin() ) {
@@ -8967,7 +8981,7 @@
8967
  $this->_logger->entrance();
8968
 
8969
  if ( ! $this->_is_network_active ) {
8970
- FS_Clone_Manager::instance()->store_new_blog_install_info( $blog_id );
8971
  return;
8972
  }
8973
 
@@ -9012,7 +9026,7 @@
9012
  $this->switch_to_blog( $current_blog_id );
9013
 
9014
  if ( is_object( $site ) ) {
9015
- FS_Clone_Manager::instance()->store_new_blog_install_info( $blog_id, $site );
9016
 
9017
  // Already connected (with or without a license), so no need to continue.
9018
  return;
@@ -9080,7 +9094,7 @@
9080
  * @author Leo Fajardo (@leorw)
9081
  * @since 2.5.0
9082
  */
9083
- FS_Clone_Manager::instance()->store_new_blog_install_info( $new_blog_id, $site );
9084
  }
9085
 
9086
  /**
@@ -9611,7 +9625,7 @@
9611
  * @param string[] $override
9612
  * @param bool $include_plugins Since 1.1.8 by default include plugin changes.
9613
  * @param bool $include_themes Since 1.1.8 by default include plugin changes.
9614
- * @param bool $include_blog_data Since 2.3.0 by default include the current blog's data (language, charset, title, and URL).
9615
  *
9616
  * @return array
9617
  */
@@ -9651,10 +9665,9 @@
9651
 
9652
  $blog_data = $include_blog_data ?
9653
  array(
9654
- 'language' => get_bloginfo( 'language' ),
9655
- 'charset' => get_bloginfo( 'charset' ),
9656
  'title' => get_bloginfo( 'name' ),
9657
- 'url' => get_site_url(),
9658
  ) :
9659
  array();
9660
 
@@ -9725,8 +9738,9 @@
9725
 
9726
  $sites = self::get_sites();
9727
 
9728
- $subsite_data_by_install_id = array();
9729
- $install_url_by_install_id = array();
 
9730
 
9731
  foreach ( $sites as $site ) {
9732
  $blog_id = self::get_site_blog_id( $site );
@@ -9744,20 +9758,35 @@
9744
  continue;
9745
  }
9746
 
9747
- $install_data = $this->get_site_info( $site );
9748
 
9749
  if ( FS_Clone_Manager::instance()->is_temporary_duplicate_by_blog_id( $install_data['blog_id'] ) ) {
9750
  continue;
9751
  }
9752
 
9753
- $uid = $install_data['uid'];
9754
- $url = $install_data['url'];
 
9755
 
9756
- if ( isset( $subsite_data_by_install_id[ $install->id ] ) ) {
9757
- $clone_subsite_data = $subsite_data_by_install_id[ $install->id ];
9758
- $clone_install_url = $install_url_by_install_id[ $install->id ];
 
 
 
9759
 
9760
  if (
 
 
 
 
 
 
 
 
 
 
 
9761
  /**
9762
  * If we already have an install with the same URL as the subsite it's stored in, skip the current subsite. Otherwise, replace the existing install's data with the current subsite's install's data if the URLs match.
9763
  *
@@ -9767,6 +9796,12 @@
9767
  fs_strip_url_protocol( untrailingslashit( $clone_install_url ) ) === fs_strip_url_protocol( untrailingslashit( $clone_subsite_data['url'] ) ) ||
9768
  fs_strip_url_protocol( untrailingslashit( $install->url ) ) !== fs_strip_url_protocol( untrailingslashit( $url ) )
9769
  ) {
 
 
 
 
 
 
9770
  continue;
9771
  }
9772
  }
@@ -9774,6 +9809,7 @@
9774
  unset( $install_data['blog_id'] );
9775
  unset( $install_data['uid'] );
9776
  unset( $install_data['url'] );
 
9777
 
9778
  $install_data['is_disconnected'] = $install->is_disconnected;
9779
  $install_data['is_active'] = $this->is_active_for_site( $blog_id );
@@ -9804,8 +9840,9 @@
9804
  $install_data['uid'] = $uid;
9805
  $install_data['url'] = $url;
9806
 
9807
- $subsite_data_by_install_id[ $install->id ] = $install_data;
9808
- $install_url_by_install_id[ $install->id ] = $install->url;
 
9809
  }
9810
  }
9811
  }
@@ -9814,7 +9851,7 @@
9814
 
9815
  $installs_data = array_merge(
9816
  $installs_data,
9817
- array_values( $subsite_data_by_install_id )
9818
  );
9819
 
9820
  if ( 0 < count( $installs_data ) && ( $is_common_diff_for_any_site || ! $only_diff ) ) {
@@ -9854,8 +9891,12 @@
9854
  if ( ( is_bool( $install->{$p} ) || ! empty( $install->{$p} ) ) &&
9855
  $install->{$p} != $v
9856
  ) {
9857
- $install->{$p} = $v;
9858
- $diff[ $p ] = $v;
 
 
 
 
9859
  }
9860
  } else {
9861
  $special[ $p ] = $v;
@@ -10456,7 +10497,7 @@
10456
  * @return string
10457
  */
10458
  function get_premium_slug() {
10459
- return is_object( $this->_plugin ) ?
10460
  $this->_plugin->premium_slug :
10461
  "{$this->_slug}-premium";
10462
  }
@@ -12581,7 +12622,7 @@
12581
  } else {
12582
  $url = is_object( $site ) ?
12583
  $site->siteurl :
12584
- get_site_url( $blog_id );
12585
 
12586
  $disconnected_site_ids[] = $blog_id;
12587
  }
@@ -15876,7 +15917,7 @@
15876
  $address_to_blog_map = array();
15877
  foreach ( $sites as $site ) {
15878
  $blog_id = self::get_site_blog_id( $site );
15879
- $address = trailingslashit( fs_strip_url_protocol( get_site_url( $blog_id ) ) );
15880
  $address_to_blog_map[ $address ] = $blog_id;
15881
  }
15882
 
@@ -16103,16 +16144,19 @@
16103
  * @since 2.0.0
16104
  *
16105
  * @param array|WP_Site|null $site
 
16106
  *
16107
  * @return array
16108
  */
16109
- function get_site_info( $site = null ) {
16110
  $this->_logger->entrance();
16111
 
16112
  $switched = false;
16113
 
 
 
16114
  if ( is_null( $site ) ) {
16115
- $url = get_site_url();
16116
  $name = get_bloginfo( 'name' );
16117
  $blog_id = null;
16118
  } else {
@@ -16124,26 +16168,38 @@
16124
  }
16125
 
16126
  if ( $site instanceof WP_Site ) {
16127
- $url = $site->siteurl;
16128
- $name = $site->blogname;
 
16129
  } else {
16130
- $url = get_site_url( $blog_id );
16131
  $name = get_bloginfo( 'name' );
16132
  }
16133
  }
16134
 
 
 
 
 
 
 
 
 
16135
  $info = array(
16136
  'uid' => $this->get_anonymous_id( $blog_id ),
16137
  'url' => $url,
16138
  'title' => $name,
16139
- 'language' => get_bloginfo( 'language' ),
16140
- 'charset' => get_bloginfo( 'charset' ),
16141
  );
16142
 
16143
  if ( is_numeric( $blog_id ) ) {
16144
  $info['blog_id'] = $blog_id;
16145
  }
16146
 
 
 
 
 
16147
  if ( $switched ) {
16148
  restore_current_blog();
16149
  }
@@ -17081,6 +17137,7 @@
17081
  }
17082
 
17083
  if (
 
17084
  $this->is_clone() &&
17085
  empty( FS_Clone_Manager::instance()->get_clone_identification_timestamp() )
17086
  ) {
@@ -17164,20 +17221,129 @@
17164
  * @return array
17165
  */
17166
  private function get_versions() {
17167
- $versions = array();
17168
- $versions['platform_version'] = get_bloginfo( 'version' );
17169
- $versions['sdk_version'] = $this->version;
17170
- $versions['programming_language_version'] = phpversion();
 
17171
 
17172
  foreach ( $versions as $k => $version ) {
17173
- if ( is_string( $versions[ $k ] ) && ! empty( $versions[ $k ] ) ) {
17174
- $versions[ $k ] = substr( $versions[ $k ], 0, 16 );
17175
- }
17176
  }
17177
 
17178
  return $versions;
17179
  }
17180
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17181
  /**
17182
  * @author Leo Fajardo (@leorw)
17183
  * @since 2.3.0
@@ -17230,23 +17396,22 @@
17230
  $versions = $this->get_versions();
17231
 
17232
  $params = array_merge( $versions, array(
17233
- 'user_firstname' => $current_user->user_firstname,
17234
- 'user_lastname' => $current_user->user_lastname,
17235
- 'user_nickname' => $current_user->user_nicename,
17236
- 'user_email' => $current_user->user_email,
17237
- 'user_ip' => WP_FS__REMOTE_ADDR,
17238
- 'plugin_slug' => $this->_slug,
17239
- 'plugin_id' => $this->get_id(),
17240
- 'plugin_public_key' => $this->get_public_key(),
17241
- 'plugin_version' => $this->get_plugin_version(),
17242
- 'return_url' => fs_nonce_url( $return_url, $activation_action ),
17243
- 'account_url' => fs_nonce_url( $this->_get_admin_page_url(
17244
  'account',
17245
  array( 'fs_action' => 'sync_user' )
17246
  ), 'sync_user' ),
17247
- 'is_premium' => $this->is_premium(),
17248
- 'is_active' => true,
17249
- 'is_uninstalled' => false,
 
17250
  ) );
17251
 
17252
  if ( $this->is_addon() ) {
@@ -17271,8 +17436,7 @@
17271
  'site_uid' => $site['uid'],
17272
  'site_url' => $site['url'],
17273
  'site_name' => $site['title'],
17274
- 'language' => $site['language'],
17275
- 'charset' => $site['charset'],
17276
  ) );
17277
  }
17278
 
@@ -17648,11 +17812,7 @@
17648
  $this->_admin_notices->remove_sticky( 'connect_account' );
17649
 
17650
  if ( $this->is_pending_activation() || ! $this->has_settings_menu() ) {
17651
- // Remove pending activation sticky notice (if still exist).
17652
- $this->_admin_notices->remove_sticky( 'activation_pending' );
17653
-
17654
- // Remove plugin from pending activation mode.
17655
- unset( $this->_storage->is_pending_activation );
17656
 
17657
  if ( ! $this->is_paying_or_trial() ) {
17658
  $this->_admin_notices->add_sticky(
@@ -18570,9 +18730,7 @@
18570
  $parent_fs->_admin_notices->remove_sticky( 'connect_account' );
18571
 
18572
  if ( $parent_fs->is_pending_activation() ) {
18573
- $parent_fs->_admin_notices->remove_sticky( 'activation_pending' );
18574
-
18575
- unset( $parent_fs->_storage->is_pending_activation );
18576
  }
18577
 
18578
  // Get user information based on parent's plugin.
@@ -19607,10 +19765,10 @@
19607
  * @uses do_action()
19608
  */
19609
  function do_action( $tag, $arg = '' ) {
19610
- $this->_logger->entrance( $tag );
19611
-
19612
  $args = func_get_args();
19613
 
 
 
19614
  call_user_func_array( 'do_action', array_merge(
19615
  array( $this->get_action_tag( $tag ) ),
19616
  array_slice( $args, 1 ) )
@@ -19750,6 +19908,30 @@
19750
  wp_send_json( $result );
19751
  }
19752
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19753
  /**
19754
  * Apply filter, specific for the current context plugin.
19755
  *
@@ -19764,9 +19946,10 @@
19764
  * @uses apply_filters()
19765
  */
19766
  function apply_filters( $tag, $value ) {
 
 
19767
  $this->_logger->entrance( $tag );
19768
 
19769
- $args = func_get_args();
19770
  array_unshift( $args, $this->get_unique_affix() );
19771
 
19772
  return call_user_func_array( 'fs_apply_filter', $args );
@@ -22967,7 +23150,7 @@
22967
  sprintf(
22968
  $this->get_text_inline( 'We will no longer be sending any usage data of %s on %s to %s.', 'opted-out-successfully' ),
22969
  $this->get_plugin_title(),
22970
- fs_strip_url_protocol( get_site_url( $blog_id ) ),
22971
  sprintf(
22972
  '<a href="%s" target="_blank" rel="noopener">%s</a>',
22973
  'https://freemius.com',
@@ -23693,7 +23876,7 @@
23693
  ! $this->is_live(),
23694
  $this->_site->secret_key,
23695
  $this->get_sdk_version(),
23696
- get_site_url()
23697
  );
23698
  }
23699
 
@@ -23734,7 +23917,7 @@
23734
  $this->_store_site();
23735
  }
23736
 
23737
- if ( fs_strip_url_protocol( $stored_remote_url ) !== fs_strip_url_protocol( trailingslashit( get_site_url() ) ) ) {
23738
  FS_Clone_Manager::instance()->maybe_run_clone_resolution();
23739
  }
23740
  }
377
  const REASON_DIDNT_WORK_AS_EXPECTED = 14;
378
  const REASON_TEMPORARY_DEACTIVATION = 15;
379
 
380
+ #endregion
381
+
382
  /**
383
  * @author Leo Fajardo (@leorw)
384
  * @since 2.3.1
394
  */
395
  private $_pricing_js_path = null;
396
 
397
+ const VERSION_MAX_CHARS = 16;
398
+ const LANGUAGE_MAX_CHARS = 8;
399
 
400
  /* Ctor
401
  ------------------------------------------------------------------------------------------------------------------*/
1499
  }
1500
  }
1501
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1502
  /**
1503
  * Opens the support forum subemenu item in a new browser page.
1504
  *
3551
  $clone_manager = FS_Clone_Manager::instance();
3552
  add_action( 'init', array( $clone_manager, '_init' ) );
3553
 
 
3554
  add_action( 'admin_footer', array( 'Freemius', '_open_support_forum_in_new_page' ) );
3555
 
3556
  if ( self::is_plugins_page() || self::is_themes_page() ) {
3597
  }
3598
 
3599
  return (
3600
+ trailingslashit( fs_strip_url_protocol( $this->_site->url ) ) !== self::get_unfiltered_site_url( null, true, true )
3601
  );
3602
  }
3603
 
3604
+ /**
3605
+ * @author Leo Fajardo (@leorw)
3606
+ * @since 2.5.0
3607
+ *
3608
+ * @param int|null $blog_id
3609
+ * @param bool $strip_protocol
3610
+ * @param bool $add_trailing_slash
3611
+ *
3612
+ * @return string
3613
+ */
3614
+ static function get_unfiltered_site_url( $blog_id = null, $strip_protocol = false, $add_trailing_slash = false ) {
3615
+ global $wp_filter;
3616
+
3617
+ $site_url_filters = array(
3618
+ 'site_url' => null,
3619
+ 'pre_option_siteurl' => null,
3620
+ 'default_option_siteurl' => null,
3621
+ 'option_siteurl' => null,
3622
+ );
3623
+
3624
+ // Detach all URL-related filters to get the actual site's URL (stripped of potential manipulations by multilingual plugins).
3625
+ foreach ( $site_url_filters as $hook_name => $site_url_filter ) {
3626
+ if ( ! empty( $wp_filter[ $hook_name ] ) ) {
3627
+ $site_url_filters[ $hook_name ] = $wp_filter[ $hook_name ];
3628
+ unset( $wp_filter[ $hook_name ] );
3629
+ }
3630
+ }
3631
+
3632
+ $url = get_site_url( $blog_id );
3633
+
3634
+ // Re-attach the filters back.
3635
+ foreach ( $site_url_filters as $hook_name => $site_url_filter ) {
3636
+ if ( ! empty( $site_url_filter ) ) {
3637
+ $wp_filter[ $hook_name ] = $site_url_filter;
3638
+ }
3639
+ }
3640
+
3641
+ if ( $strip_protocol ) {
3642
+ $url = fs_strip_url_protocol( $url );
3643
+ }
3644
+
3645
+ if ( $add_trailing_slash ) {
3646
+ $url = trailingslashit( $url );
3647
+ }
3648
+
3649
+ return $url;
3650
+ }
3651
+
3652
  /**
3653
  * @author Leo Fajardo (@leorw)
3654
  * @since 2.5.0
3675
  if (
3676
  is_object( $this->_license ) &&
3677
  ! $this->_license->is_utilized(
3678
+ ( WP_FS__IS_LOCALHOST_FOR_SERVER || FS_Site::is_localhost_by_address( self::get_unfiltered_site_url() ) )
3679
  )
3680
  ) {
3681
  $license_key = $this->_license->secret_key;
4325
  $unique_id = self::$_accounts->get_option( 'unique_id', null, $blog_id );
4326
 
4327
  if ( empty( $unique_id ) || ! is_string( $unique_id ) ) {
4328
+ $key = self::get_unfiltered_site_url( $blog_id, true );
4329
 
4330
  $secure_auth = defined( 'SECURE_AUTH_KEY' ) ? SECURE_AUTH_KEY : '';
4331
  if ( empty( $secure_auth ) ||
6679
  return $this->_storage->get( 'is_pending_activation', false );
6680
  }
6681
 
6682
+ /**
6683
+ * @author Leo Fajardo (@leorw)
6684
+ * @since 2.5.0
6685
+ */
6686
+ private function clear_pending_activation_mode() {
6687
+ // Remove the pending activation sticky notice (if it still exists).
6688
+ $this->_admin_notices->remove_sticky( 'activation_pending' );
6689
+
6690
+ // Clear the plugin's pending activation mode.
6691
+ unset( $this->_storage->is_pending_activation );
6692
+ }
6693
+
6694
  /**
6695
  * Check if plugin must be WordPress.org compliant.
6696
  *
6767
  private function get_cron_blog_id( $name ) {
6768
  $this->_logger->entrance( $name );
6769
 
6770
+ if ( ! is_multisite() ) {
6771
+ // Not a multisite.
6772
+ return 0;
6773
+ }
6774
+
6775
  $cron_data = $this->get_cron_data( $name );
6776
 
6777
  return ( is_object( $cron_data ) && is_numeric( $cron_data->blog_id ) ) ?
6945
  return;
6946
  }
6947
 
6948
+ $cron_blog_id = $this->get_cron_blog_id( $name );
 
 
 
 
 
 
 
6949
 
6950
  $this->clear_cron_data( $name );
6951
 
6982
  return false;
6983
  }
6984
 
6985
+ $cron_blog_id = $this->get_cron_blog_id( $name );
 
 
 
 
 
 
 
6986
 
6987
  if ( 0 < $cron_blog_id ) {
6988
  switch_to_blog( $cron_blog_id );
7365
  * @param int $except_blog_id Since 2.0.0 when running in a multisite network environment, the cron execution is consolidated. This param allows excluding excluded specified blog ID from being the cron executor.
7366
  */
7367
  private function schedule_install_sync( $except_blog_id = 0 ) {
7368
+ if ( $this->is_clone() ) {
7369
+ return;
7370
+ }
7371
+
7372
  $this->schedule_cron( 'install_sync', 'install_sync', 'single', WP_FS__SCRIPT_START_TIME, false, $except_blog_id );
7373
  }
7374
 
7441
  * @param int|null $current_blog_id
7442
  */
7443
  function _sync_install_cron_method( array $blog_ids, $current_blog_id = null ) {
 
 
 
 
7444
  if ( $this->is_registered() ) {
7445
  if ( 1 < count( $blog_ids ) ) {
7446
  $this->sync_installs( array(), true );
8082
  ( current_filter() !== ( 'activate_' . $this->_free_plugin_basename ) ) :
8083
  $this->is_premium();
8084
 
8085
+ if ( $is_premium_version_activation && $this->is_pending_activation() ) {
8086
+ $this->clear_pending_activation_mode();
8087
+ }
8088
+
8089
  $this->_logger->info( 'Activating ' . ( $is_premium_version_activation ? 'premium' : 'free' ) . ' plugin version.' );
8090
 
8091
  if ( $this->is_plugin() ) {
8981
  $this->_logger->entrance();
8982
 
8983
  if ( ! $this->_is_network_active ) {
8984
+ FS_Clone_Manager::instance()->store_blog_install_info( $blog_id );
8985
  return;
8986
  }
8987
 
9026
  $this->switch_to_blog( $current_blog_id );
9027
 
9028
  if ( is_object( $site ) ) {
9029
+ FS_Clone_Manager::instance()->store_blog_install_info( $blog_id, $site );
9030
 
9031
  // Already connected (with or without a license), so no need to continue.
9032
  return;
9094
  * @author Leo Fajardo (@leorw)
9095
  * @since 2.5.0
9096
  */
9097
+ FS_Clone_Manager::instance()->store_blog_install_info( $new_blog_id, $site );
9098
  }
9099
 
9100
  /**
9625
  * @param string[] $override
9626
  * @param bool $include_plugins Since 1.1.8 by default include plugin changes.
9627
  * @param bool $include_themes Since 1.1.8 by default include plugin changes.
9628
+ * @param bool $include_blog_data Since 2.3.0 by default include the current blog's data (language, title, and URL).
9629
  *
9630
  * @return array
9631
  */
9665
 
9666
  $blog_data = $include_blog_data ?
9667
  array(
9668
+ 'language' => self::get_sanitized_language(),
 
9669
  'title' => get_bloginfo( 'name' ),
9670
+ 'url' => self::get_unfiltered_site_url(),
9671
  ) :
9672
  array();
9673
 
9738
 
9739
  $sites = self::get_sites();
9740
 
9741
+ $subsite_data_for_api_by_install_id = array();
9742
+ $install_url_by_install_id = array();
9743
+ $subsite_registration_date_by_install_id = array();
9744
 
9745
  foreach ( $sites as $site ) {
9746
  $blog_id = self::get_site_blog_id( $site );
9758
  continue;
9759
  }
9760
 
9761
+ $install_data = $this->get_site_info( $site, true );
9762
 
9763
  if ( FS_Clone_Manager::instance()->is_temporary_duplicate_by_blog_id( $install_data['blog_id'] ) ) {
9764
  continue;
9765
  }
9766
 
9767
+ $uid = $install_data['uid'];
9768
+ $url = $install_data['url'];
9769
+ $registration_date = $install_data['registration_date'];
9770
 
9771
+ if ( isset( $subsite_data_for_api_by_install_id[ $install->id ] ) ) {
9772
+ $clone_subsite_data = $subsite_data_for_api_by_install_id[ $install->id ];
9773
+ $clone_install_url = $install_url_by_install_id[ $install->id ];
9774
+ $clone_subsite_registration_date = $subsite_registration_date_by_install_id[ $install->id ];
9775
+
9776
+ $skip = false;
9777
 
9778
  if (
9779
+ ! empty( $install_data['registration_date'] ) &&
9780
+ ! empty( $clone_subsite_registration_date )
9781
+ ) {
9782
+ /**
9783
+ * If the current subsite was created after the other subsite that is also linked to the same install ID, we assume that it's a clone (not the original), and therefore, would skip its processing.
9784
+ *
9785
+ * @author Leo Fajardo (@leorw)
9786
+ * @since 2.5.1
9787
+ */
9788
+ $skip = ( strtotime( $install_data['registration_date'] ) > strtotime( $clone_subsite_registration_date ) );
9789
+ } else if (
9790
  /**
9791
  * If we already have an install with the same URL as the subsite it's stored in, skip the current subsite. Otherwise, replace the existing install's data with the current subsite's install's data if the URLs match.
9792
  *
9796
  fs_strip_url_protocol( untrailingslashit( $clone_install_url ) ) === fs_strip_url_protocol( untrailingslashit( $clone_subsite_data['url'] ) ) ||
9797
  fs_strip_url_protocol( untrailingslashit( $install->url ) ) !== fs_strip_url_protocol( untrailingslashit( $url ) )
9798
  ) {
9799
+ $skip = true;
9800
+ }
9801
+
9802
+ if ( $skip ) {
9803
+ // Store the skipped subsite's ID so that the clone resolution manager can try to resolve the clone install that is stored in that subsite later on.
9804
+ FS_Clone_Manager::instance()->store_blog_install_info( $blog_id );
9805
  continue;
9806
  }
9807
  }
9809
  unset( $install_data['blog_id'] );
9810
  unset( $install_data['uid'] );
9811
  unset( $install_data['url'] );
9812
+ unset( $install_data['registration_date'] );
9813
 
9814
  $install_data['is_disconnected'] = $install->is_disconnected;
9815
  $install_data['is_active'] = $this->is_active_for_site( $blog_id );
9840
  $install_data['uid'] = $uid;
9841
  $install_data['url'] = $url;
9842
 
9843
+ $subsite_data_for_api_by_install_id[ $install->id ] = $install_data;
9844
+ $install_url_by_install_id[ $install->id ] = $install->url;
9845
+ $subsite_registration_date_by_install_id[ $install->id ] = $registration_date;
9846
  }
9847
  }
9848
  }
9851
 
9852
  $installs_data = array_merge(
9853
  $installs_data,
9854
+ array_values( $subsite_data_for_api_by_install_id )
9855
  );
9856
 
9857
  if ( 0 < count( $installs_data ) && ( $is_common_diff_for_any_site || ! $only_diff ) ) {
9891
  if ( ( is_bool( $install->{$p} ) || ! empty( $install->{$p} ) ) &&
9892
  $install->{$p} != $v
9893
  ) {
9894
+ $val = self::get_api_sanitized_property( $p, $v );
9895
+
9896
+ if ( $install->{$p} != $val ) {
9897
+ $install->{$p} = $val;
9898
+ $diff[ $p ] = $val;
9899
+ }
9900
  }
9901
  } else {
9902
  $special[ $p ] = $v;
10497
  * @return string
10498
  */
10499
  function get_premium_slug() {
10500
+ return ( is_object( $this->_plugin ) && ! empty( $this->_plugin->premium_slug ) ) ?
10501
  $this->_plugin->premium_slug :
10502
  "{$this->_slug}-premium";
10503
  }
12622
  } else {
12623
  $url = is_object( $site ) ?
12624
  $site->siteurl :
12625
+ self::get_unfiltered_site_url( $blog_id );
12626
 
12627
  $disconnected_site_ids[] = $blog_id;
12628
  }
15917
  $address_to_blog_map = array();
15918
  foreach ( $sites as $site ) {
15919
  $blog_id = self::get_site_blog_id( $site );
15920
+ $address = self::get_unfiltered_site_url( $blog_id, true, true );
15921
  $address_to_blog_map[ $address ] = $blog_id;
15922
  }
15923
 
16144
  * @since 2.0.0
16145
  *
16146
  * @param array|WP_Site|null $site
16147
+ * @param bool $load_registration Since 2.5.1 When set to `true` the method will attempt to return the subsite's registration date, regardless of the `$site` type and value. In most calls, the registration date will be returned anyway, even when the value is `false`. This param is purely for performance optimization.
16148
  *
16149
  * @return array
16150
  */
16151
+ function get_site_info( $site = null, $load_registration = false ) {
16152
  $this->_logger->entrance();
16153
 
16154
  $switched = false;
16155
 
16156
+ $registration_date = null;
16157
+
16158
  if ( is_null( $site ) ) {
16159
+ $url = self::get_unfiltered_site_url();
16160
  $name = get_bloginfo( 'name' );
16161
  $blog_id = null;
16162
  } else {
16168
  }
16169
 
16170
  if ( $site instanceof WP_Site ) {
16171
+ $url = $site->siteurl;
16172
+ $name = $site->blogname;
16173
+ $registration_date = $site->registered;
16174
  } else {
16175
+ $url = self::get_unfiltered_site_url( $blog_id );
16176
  $name = get_bloginfo( 'name' );
16177
  }
16178
  }
16179
 
16180
+ if ( empty( $registration_date ) && $load_registration ) {
16181
+ $blog_details = get_blog_details( $blog_id, false );
16182
+
16183
+ if ( is_object( $blog_details ) && isset( $blog_details->registered ) ) {
16184
+ $registration_date = $blog_details->registered;
16185
+ }
16186
+ }
16187
+
16188
  $info = array(
16189
  'uid' => $this->get_anonymous_id( $blog_id ),
16190
  'url' => $url,
16191
  'title' => $name,
16192
+ 'language' => self::get_sanitized_language(),
 
16193
  );
16194
 
16195
  if ( is_numeric( $blog_id ) ) {
16196
  $info['blog_id'] = $blog_id;
16197
  }
16198
 
16199
+ if ( ! empty( $registration_date ) ) {
16200
+ $info[ 'registration_date' ] = $registration_date;
16201
+ }
16202
+
16203
  if ( $switched ) {
16204
  restore_current_blog();
16205
  }
17137
  }
17138
 
17139
  if (
17140
+ $this->is_user_in_admin() &&
17141
  $this->is_clone() &&
17142
  empty( FS_Clone_Manager::instance()->get_clone_identification_timestamp() )
17143
  ) {
17221
  * @return array
17222
  */
17223
  private function get_versions() {
17224
+ $versions = array(
17225
+ 'platform_version' => get_bloginfo( 'version' ),
17226
+ 'sdk_version' => $this->version,
17227
+ 'programming_language_version' => phpversion(),
17228
+ );
17229
 
17230
  foreach ( $versions as $k => $version ) {
17231
+ $versions[ $k ] = self::get_api_sanitized_property( $k, $version );
 
 
17232
  }
17233
 
17234
  return $versions;
17235
  }
17236
 
17237
+ /**
17238
+ * Get sanitized site language.
17239
+ *
17240
+ * @param string $language
17241
+ * @param int $max_len
17242
+ *
17243
+ * @since 2.5.1
17244
+ * @author Vova Feldman (@svovaf)
17245
+ *
17246
+ * @return string
17247
+ */
17248
+ private static function get_sanitized_language( $language = '', $max_len = self::LANGUAGE_MAX_CHARS ) {
17249
+ if ( empty( $language ) ) {
17250
+ $language = get_bloginfo( 'language' );
17251
+ }
17252
+
17253
+ return substr( $language, 0, $max_len );
17254
+ }
17255
+
17256
+ /**
17257
+ * Get core version stripped from pre-release and build.
17258
+ *
17259
+ * @since 2.5.1
17260
+ * @author Vova Feldman (@svovaf)
17261
+ *
17262
+ * @param string $version
17263
+ * @param int $parts
17264
+ * @param int $max_len
17265
+ * @param bool $include_pre_release
17266
+ *
17267
+ * @return string
17268
+ */
17269
+ private static function get_core_version(
17270
+ $version,
17271
+ $parts = 3,
17272
+ $max_len = self::VERSION_MAX_CHARS,
17273
+ $include_pre_release = false
17274
+ ) {
17275
+ if ( empty( $version ) ) {
17276
+ // Version is empty.
17277
+ return '';
17278
+ }
17279
+
17280
+ if ( is_numeric( $version ) ) {
17281
+ $is_float_version = is_float( $version );
17282
+
17283
+ $version = (string) $version;
17284
+
17285
+ /**
17286
+ * Casting a whole float number to a string cuts the decimal point. This part make sure to add the missing decimal part to the version.
17287
+ */
17288
+ if ( $is_float_version && false === strpos( $version, '.' ) ) {
17289
+ $version .= '.0';
17290
+ }
17291
+ }
17292
+
17293
+ if ( ! is_string( $version ) ) {
17294
+ return '';
17295
+ }
17296
+
17297
+ if ( $parts < 1 ) {
17298
+ return '';
17299
+ }
17300
+
17301
+ $pre_release_regex = $include_pre_release ?
17302
+ '(\-(alpha|beta|RC)([0-9]+)?)?' :
17303
+ '';
17304
+
17305
+ if ( 0 === preg_match( '/^([0-9]+(\.[0-9]+){0,' . ( $parts - 1 ) . '}' . $pre_release_regex . ')/i', $version, $matches ) ) {
17306
+ // Version is not starting with a digit.
17307
+ return '';
17308
+ }
17309
+
17310
+ return substr( $matches[1], 0, $max_len );
17311
+ }
17312
+
17313
+ /**
17314
+ * @param string $prop
17315
+ * @param mixed $val
17316
+ *
17317
+ * @return mixed
17318
+ *@author Vova Feldman (@svovaf)
17319
+ *
17320
+ * @since 2.5.1
17321
+ */
17322
+ private static function get_api_sanitized_property( $prop, $val ) {
17323
+ if ( ! is_string( $val ) || empty( $val ) ) {
17324
+ return $val;
17325
+ }
17326
+
17327
+ switch ( $prop ) {
17328
+ case 'programming_language_version':
17329
+ // Get core PHP version, which can have up to 3 parts (ignore pre-releases).
17330
+ return self::get_core_version( $val );
17331
+ case 'platform_version':
17332
+ // Get the exact WordPress version, which can have up to 3 parts (including pre-releases).
17333
+ return self::get_core_version( $val, 3, self::VERSION_MAX_CHARS, true );
17334
+ case 'sdk_version':
17335
+ // Get the exact SDK version, which can have up to 4 parts.
17336
+ return self::get_core_version( $val, 4 );
17337
+ case 'version':
17338
+ // Get the entire version but just limited in length.
17339
+ return substr( $val, 0, self::VERSION_MAX_CHARS );
17340
+ case 'language':
17341
+ return self::get_sanitized_language( $val );
17342
+ default:
17343
+ return $val;
17344
+ }
17345
+ }
17346
+
17347
  /**
17348
  * @author Leo Fajardo (@leorw)
17349
  * @since 2.3.0
17396
  $versions = $this->get_versions();
17397
 
17398
  $params = array_merge( $versions, array(
17399
+ 'user_firstname' => $current_user->user_firstname,
17400
+ 'user_lastname' => $current_user->user_lastname,
17401
+ 'user_email' => $current_user->user_email,
17402
+ 'plugin_slug' => $this->_slug,
17403
+ 'plugin_id' => $this->get_id(),
17404
+ 'plugin_public_key' => $this->get_public_key(),
17405
+ 'plugin_version' => $this->get_plugin_version(),
17406
+ 'return_url' => fs_nonce_url( $return_url, $activation_action ),
17407
+ 'account_url' => fs_nonce_url( $this->_get_admin_page_url(
 
 
17408
  'account',
17409
  array( 'fs_action' => 'sync_user' )
17410
  ), 'sync_user' ),
17411
+ 'is_premium' => $this->is_premium(),
17412
+ 'is_active' => true,
17413
+ 'is_uninstalled' => false,
17414
+ 'is_localhost' => WP_FS__IS_LOCALHOST,
17415
  ) );
17416
 
17417
  if ( $this->is_addon() ) {
17436
  'site_uid' => $site['uid'],
17437
  'site_url' => $site['url'],
17438
  'site_name' => $site['title'],
17439
+ 'language' => self::get_sanitized_language( $site['language'] ),
 
17440
  ) );
17441
  }
17442
 
17812
  $this->_admin_notices->remove_sticky( 'connect_account' );
17813
 
17814
  if ( $this->is_pending_activation() || ! $this->has_settings_menu() ) {
17815
+ $this->clear_pending_activation_mode();
 
 
 
 
17816
 
17817
  if ( ! $this->is_paying_or_trial() ) {
17818
  $this->_admin_notices->add_sticky(
18730
  $parent_fs->_admin_notices->remove_sticky( 'connect_account' );
18731
 
18732
  if ( $parent_fs->is_pending_activation() ) {
18733
+ $parent_fs->clear_pending_activation_mode();
 
 
18734
  }
18735
 
18736
  // Get user information based on parent's plugin.
19765
  * @uses do_action()
19766
  */
19767
  function do_action( $tag, $arg = '' ) {
 
 
19768
  $args = func_get_args();
19769
 
19770
+ $this->_logger->entrance( $tag );
19771
+
19772
  call_user_func_array( 'do_action', array_merge(
19773
  array( $this->get_action_tag( $tag ) ),
19774
  array_slice( $args, 1 ) )
19908
  wp_send_json( $result );
19909
  }
19910
 
19911
+ /**
19912
+ * Returns an AJAX URL with a special extra param to indicate whether the request was triggered from the network admin or blog admin.
19913
+ *
19914
+ * @author Vova Feldman (@svovaf)
19915
+ * @since 2.5.1
19916
+ *
19917
+ * @param string $wrap_with By default, returns the AJAX URL wrapped with single quotes.
19918
+ *
19919
+ * @return string
19920
+ */
19921
+ static function ajax_url( $wrap_with = "'") {
19922
+ if ( fs_is_network_admin() ) {
19923
+ $param_name = '_fs_network_admin';
19924
+ } else {
19925
+ $param_name = '_fs_blog_admin';
19926
+ }
19927
+
19928
+ $url = admin_url( 'admin-ajax.php', 'relative' );
19929
+ $url .= ( false === strpos( $url, '?' ) ) ? '?' : '&';
19930
+ $url .= "{$param_name}=true";
19931
+
19932
+ return "{$wrap_with}{$url}{$wrap_with}";
19933
+ }
19934
+
19935
  /**
19936
  * Apply filter, specific for the current context plugin.
19937
  *
19946
  * @uses apply_filters()
19947
  */
19948
  function apply_filters( $tag, $value ) {
19949
+ $args = func_get_args();
19950
+
19951
  $this->_logger->entrance( $tag );
19952
 
 
19953
  array_unshift( $args, $this->get_unique_affix() );
19954
 
19955
  return call_user_func_array( 'fs_apply_filter', $args );
23150
  sprintf(
23151
  $this->get_text_inline( 'We will no longer be sending any usage data of %s on %s to %s.', 'opted-out-successfully' ),
23152
  $this->get_plugin_title(),
23153
+ self::get_unfiltered_site_url( $blog_id, true ),
23154
  sprintf(
23155
  '<a href="%s" target="_blank" rel="noopener">%s</a>',
23156
  'https://freemius.com',
23876
  ! $this->is_live(),
23877
  $this->_site->secret_key,
23878
  $this->get_sdk_version(),
23879
+ self::get_unfiltered_site_url()
23880
  );
23881
  }
23882
 
23917
  $this->_store_site();
23918
  }
23919
 
23920
+ if ( fs_strip_url_protocol( $stored_remote_url ) !== self::get_unfiltered_site_url( null, true, true ) ) {
23921
  FS_Clone_Manager::instance()->maybe_run_clone_resolution();
23922
  }
23923
  }
vendor/freemius/wordpress-sdk/includes/class-fs-logger.php CHANGED
@@ -38,9 +38,10 @@
38
  private static $_HOOKED_FOOTER = false;
39
 
40
  private function __construct( $id, $on = false, $echo = false ) {
 
 
41
  $this->_id = $id;
42
 
43
- $bt = debug_backtrace();
44
  $caller = $bt[2];
45
 
46
  if ( false !== strpos( $caller['file'], 'plugins' ) ) {
38
  private static $_HOOKED_FOOTER = false;
39
 
40
  private function __construct( $id, $on = false, $echo = false ) {
41
+ $bt = debug_backtrace();
42
+
43
  $this->_id = $id;
44
 
 
45
  $caller = $bt[2];
46
 
47
  if ( false !== strpos( $caller['file'], 'plugins' ) ) {
vendor/freemius/wordpress-sdk/includes/entities/class-fs-site.php CHANGED
@@ -39,10 +39,6 @@
39
  * @var string E.g. en-GB
40
  */
41
  public $language;
42
- /**
43
- * @var string E.g. UTF-8
44
- */
45
- public $charset;
46
  /**
47
  * @var string Platform version (e.g WordPress version).
48
  */
@@ -256,4 +252,4 @@
256
  function is_beta() {
257
  return ( isset( $this->is_beta ) && true === $this->is_beta );
258
  }
259
- }
39
  * @var string E.g. en-GB
40
  */
41
  public $language;
 
 
 
 
42
  /**
43
  * @var string Platform version (e.g WordPress version).
44
  */
252
  function is_beta() {
253
  return ( isset( $this->is_beta ) && true === $this->is_beta );
254
  }
255
+ }
vendor/freemius/wordpress-sdk/includes/fs-essential-functions.php CHANGED
@@ -151,31 +151,19 @@
151
 
152
  if ( ! function_exists( 'fs_get_ip' ) ) {
153
  /**
154
- * Get client IP.
155
- *
 
 
156
  * @author Vova Feldman (@svovaf)
157
  * @since 1.1.2
158
  *
159
  * @return string|null
160
  */
161
  function fs_get_ip() {
162
- $fields = array(
163
- 'HTTP_CF_CONNECTING_IP',
164
- 'HTTP_CLIENT_IP',
165
- 'HTTP_X_FORWARDED_FOR',
166
- 'HTTP_X_FORWARDED',
167
- 'HTTP_FORWARDED_FOR',
168
- 'HTTP_FORWARDED',
169
- 'REMOTE_ADDR',
170
- );
171
-
172
- foreach ( $fields as $ip_field ) {
173
- if ( ! empty( $_SERVER[ $ip_field ] ) ) {
174
- return $_SERVER[ $ip_field ];
175
- }
176
- }
177
-
178
- return null;
179
  }
180
  }
181
 
151
 
152
  if ( ! function_exists( 'fs_get_ip' ) ) {
153
  /**
154
+ * Get server IP.
155
+ *
156
+ * @since 2.5.1 This method returns the server IP.
157
+ *
158
  * @author Vova Feldman (@svovaf)
159
  * @since 1.1.2
160
  *
161
  * @return string|null
162
  */
163
  function fs_get_ip() {
164
+ return empty( $_SERVER[ 'SERVER_ADDR' ] ) ?
165
+ null :
166
+ $_SERVER[ 'SERVER_ADDR' ];
 
 
 
 
 
 
 
 
 
 
 
 
 
 
167
  }
168
  }
169
 
vendor/freemius/wordpress-sdk/includes/managers/class-fs-clone-manager.php CHANGED
@@ -82,6 +82,10 @@
82
  * @var string
83
  */
84
  const OPTION_TEMPORARY_DUPLICATE = 'temporary_duplicate';
 
 
 
 
85
  /**
86
  * @var string
87
  */
@@ -167,6 +171,7 @@
167
  if ( Freemius::is_ajax() ) {
168
  Freemius::add_ajax_action_static( 'handle_clone_resolution', array( $this, '_clone_resolution_action_ajax_handler' ) );
169
  } else if ( ! Freemius::is_cron() && ! Freemius::is_admin_post() ) {
 
170
  $this->maybe_show_clone_admin_notice();
171
 
172
  add_action( 'admin_footer', array( $this, '_add_clone_resolution_javascript' ) );
@@ -447,7 +452,12 @@
447
  *
448
  * @return bool If managed to automatically resolve the clone.
449
  */
450
- private function try_resolve_clone_automatically( Freemius $instance, $current_url, $is_localhost, $is_clone_of_network_subsite = null ) {
 
 
 
 
 
451
  // Try to find a different install of the context product that is associated with the current URL.
452
  $associated_install = $this->find_other_install_by_url( $instance, $current_url );
453
 
@@ -472,20 +482,103 @@
472
  return false;
473
  }
474
 
475
- $is_clone_of_network_subsite = ( ! is_null( $is_clone_of_network_subsite ) ) ?
476
- $is_clone_of_network_subsite :
477
- is_object( $this->find_network_subsite_clone_install( $instance ) );
 
478
 
479
- if (
480
- $is_clone_of_network_subsite ||
481
- WP_FS__IS_LOCALHOST_FOR_SERVER ||
482
- $is_localhost
483
- ) {
484
- // If the site is a clone of another subsite in the network, or a localhost one, try to auto activate the license.
485
- return $this->delete_install_and_connect( $instance, $license->secret_key );
486
  }
487
 
488
- return false;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
489
  }
490
 
491
  /**
@@ -544,7 +637,7 @@
544
 
545
  $instance->switch_to_blog( $blog_id );
546
 
547
- $current_url = fs_strip_url_protocol( untrailingslashit( get_site_url() ) );
548
  $current_install_url = is_object( $current_install ) ?
549
  fs_strip_url_protocol( untrailingslashit( $current_install->url ) ) :
550
  null;
@@ -574,7 +667,7 @@
574
  // If there's no expected install (or it couldn't be fetched) and the current install is a clone, try to resolve the clone automatically.
575
  $is_localhost = FS_Site::is_localhost_by_address( $current_url );
576
 
577
- $resolved = $this->try_resolve_clone_automatically( $instance, $current_url, $is_localhost, is_object( $network_subsite_clone_install ) );
578
 
579
  if ( ! $resolved && is_object( $network_subsite_clone_install ) ) {
580
  if ( empty( $this->get_clone_identification_timestamp() ) ) {
@@ -594,7 +687,7 @@
594
  }
595
 
596
  /**
597
- * If a new install was created after creating a new subsite, its ID is stored in the blog-install map so that it can be recovered in case it's replaced with a clone install (e.g., when the newly created subsite is a clone).
598
  *
599
  * @author Leo Fajardo (@leorw)
600
  * @since 2.5.0
@@ -602,7 +695,7 @@
602
  * @param int $blog_id
603
  * @param FS_Site $site
604
  */
605
- function store_new_blog_install_info( $blog_id, $site = null ) {
606
  $new_blog_install_map = $this->new_blog_install_map;
607
 
608
  if (
@@ -647,7 +740,7 @@
647
  private function try_automatic_resolution() {
648
  $this->_logger->entrance();
649
 
650
- $current_url = fs_strip_url_protocol( untrailingslashit( get_site_url() ) );
651
  $is_localhost = FS_Site::is_localhost_by_address( $current_url );
652
 
653
  $require_manual_resolution = false;
@@ -663,7 +756,7 @@
663
  continue;
664
  }
665
 
666
- if ( ! $this->try_resolve_clone_automatically( $instance, $current_url, $is_localhost ) ) {
667
  $require_manual_resolution = true;
668
  }
669
  }
@@ -705,19 +798,7 @@
705
  ) );
706
  }
707
 
708
- $result = array();
709
-
710
- if ( self::OPTION_TEMPORARY_DUPLICATE === $clone_action ) {
711
- $this->store_temporary_duplicate_timestamp();
712
- } else {
713
- $result = $this->resolve_cloned_sites( $clone_action );
714
- }
715
-
716
- if ( 'temporary_duplicate_license_activation' !== $clone_action ) {
717
- $this->remove_clone_resolution_options_notice();
718
- } else {
719
- $this->remove_temporary_duplicate_notice();
720
- }
721
 
722
  Freemius::shoot_ajax_success( $result );
723
  }
@@ -726,53 +807,72 @@
726
  * @author Leo Fajardo (@leorw)
727
  * @since 2.5.0
728
  *
729
- * @param string $clone_action
 
 
 
730
  */
731
- private function resolve_cloned_sites( $clone_action ) {
732
  $this->_logger->entrance();
733
 
734
- $instances_with_clone_count = 0;
735
- $instance_with_error = null;
736
- $has_error = false;
737
 
738
- $instances = Freemius::_get_all_instances();
 
 
 
 
 
739
 
740
- foreach ( $instances as $instance ) {
741
- if ( ! $instance->is_registered() ) {
742
- continue;
743
- }
744
 
745
- if ( ! $instance->is_clone() ) {
746
- continue;
747
- }
 
 
 
 
 
748
 
749
- $instances_with_clone_count ++;
750
 
751
- if ( FS_Clone_Manager::OPTION_NEW_HOME === $clone_action ) {
752
- $instance->sync_install( array( 'is_new_site' => true ), true );
753
- } else {
754
- $instance->_handle_long_term_duplicate();
755
 
756
- if ( ! is_object( $instance->get_site() ) ) {
757
- $has_error = true;
758
 
759
- if ( ! is_object( $instance_with_error ) ) {
760
- $instance_with_error = $instance;
 
761
  }
762
  }
763
  }
764
- }
765
 
766
- $redirect_url = '';
767
 
768
- if (
769
- 1 === $instances_with_clone_count &&
770
- $has_error
771
- ) {
772
- $redirect_url = $instance_with_error->get_activation_url();
 
 
 
773
  }
774
 
775
- return ( array( 'redirect_url' => $redirect_url ) );
 
 
 
 
 
 
776
  }
777
 
778
  /**
@@ -874,7 +974,7 @@
874
  $product_ids,
875
  $product_titles,
876
  $site_urls,
877
- get_site_url(),
878
  ( count( $site_urls ) === count( $sites_with_license_urls ) ),
879
  ( count( $site_urls ) === $sites_with_premium_version_count ),
880
  $doc_url
@@ -984,10 +1084,9 @@
984
  continue;
985
  }
986
 
987
- $subsite_url = trailingslashit( get_site_url( $blog_id ) );
988
- $install_url = trailingslashit( $install->url );
989
 
990
- $has_clone = ( fs_strip_url_protocol( $install_url ) !== fs_strip_url_protocol( $subsite_url ) );
991
  }
992
  }
993
 
@@ -1184,13 +1283,17 @@
1184
  *
1185
  * @return string
1186
  */
1187
- private function get_temporary_duplicate_admin_notice_string( $site_urls, $product_titles, $module_label ) {
 
 
 
 
1188
  $this->_logger->entrance();
1189
 
1190
  $temporary_duplicate_end_date = $this->get_temporary_duplicate_expiration_timestamp();
1191
  $temporary_duplicate_end_date = date( 'M j, Y', $temporary_duplicate_end_date );
1192
 
1193
- $current_url = get_site_url();
1194
  $current_site_link = sprintf(
1195
  '<b><a href="%s" target="_blank">%s</a></b>',
1196
  $current_url,
@@ -1387,7 +1490,11 @@
1387
  * @param string $message
1388
  * @param string|null $plugin_title
1389
  */
1390
- function add_temporary_duplicate_sticky_notice( $product_ids, $message, $plugin_title = null ) {
 
 
 
 
1391
  $this->_logger->entrance();
1392
 
1393
  $this->_notices->add_sticky(
82
  * @var string
83
  */
84
  const OPTION_TEMPORARY_DUPLICATE = 'temporary_duplicate';
85
+ /**
86
+ * @var string
87
+ */
88
+ const OPTION_LONG_TERM_DUPLICATE = 'long_term_duplicate';
89
  /**
90
  * @var string
91
  */
171
  if ( Freemius::is_ajax() ) {
172
  Freemius::add_ajax_action_static( 'handle_clone_resolution', array( $this, '_clone_resolution_action_ajax_handler' ) );
173
  } else if ( ! Freemius::is_cron() && ! Freemius::is_admin_post() ) {
174
+ $this->try_resolve_clone_automatically();
175
  $this->maybe_show_clone_admin_notice();
176
 
177
  add_action( 'admin_footer', array( $this, '_add_clone_resolution_javascript' ) );
452
  *
453
  * @return bool If managed to automatically resolve the clone.
454
  */
455
+ private function try_resolve_clone_automatically_by_instance(
456
+ Freemius $instance,
457
+ $current_url,
458
+ $is_localhost,
459
+ $is_clone_of_network_subsite = null
460
+ ) {
461
  // Try to find a different install of the context product that is associated with the current URL.
462
  $associated_install = $this->find_other_install_by_url( $instance, $current_url );
463
 
482
  return false;
483
  }
484
 
485
+ if ( ! WP_FS__IS_LOCALHOST_FOR_SERVER && ! $is_localhost ) {
486
+ $is_clone_of_network_subsite = ( ! is_null( $is_clone_of_network_subsite ) ) ?
487
+ $is_clone_of_network_subsite :
488
+ is_object( $this->find_network_subsite_clone_install( $instance ) );
489
 
490
+ if ( ! $is_clone_of_network_subsite ) {
491
+ return false;
492
+ }
 
 
 
 
493
  }
494
 
495
+ // If the site is a clone of another subsite in the network, or a localhost one, try to auto activate the license.
496
+ return $this->delete_install_and_connect( $instance, $license->secret_key );
497
+ }
498
+
499
+ /**
500
+ * @author Leo Fajardo (@leorw)
501
+ * @since 2.5.0
502
+ */
503
+ private function try_resolve_clone_automatically() {
504
+ $clone_action = $this->get_clone_resolution_action_from_config();
505
+
506
+ if ( ! empty( $clone_action ) ) {
507
+ $this->try_resolve_clone_automatically_by_config( $clone_action );
508
+ return;
509
+ }
510
+
511
+ $this->try_automatic_resolution();
512
+ }
513
+
514
+ /**
515
+ * Tries to resolve the clone situation automatically based on the config in the wp-config.php file.
516
+ *
517
+ * @author Leo Fajardo (@leorw)
518
+ * @since 2.5.0
519
+ *
520
+ * @param string $clone_action
521
+ */
522
+ private function try_resolve_clone_automatically_by_config( $clone_action ) {
523
+ $fs_instances = array();
524
+
525
+ if ( self::OPTION_LONG_TERM_DUPLICATE === $clone_action ) {
526
+ $instances = Freemius::_get_all_instances();
527
+
528
+ foreach ( $instances as $instance ) {
529
+ if ( ! $instance->is_registered() ) {
530
+ continue;
531
+ }
532
+
533
+ if ( ! $instance->is_clone() ) {
534
+ continue;
535
+ }
536
+
537
+ $license = $instance->has_features_enabled_license() ?
538
+ $instance->_get_license() :
539
+ null;
540
+
541
+ if (
542
+ is_object( $license ) &&
543
+ ! $license->is_utilized(
544
+ ( WP_FS__IS_LOCALHOST_FOR_SERVER || FS_Site::is_localhost_by_address( Freemius::get_unfiltered_site_url() ) )
545
+ )
546
+ ) {
547
+ $fs_instances[] = $instance;
548
+ }
549
+ }
550
+
551
+ if ( empty( $fs_instances ) ) {
552
+ return;
553
+ }
554
+ }
555
+
556
+ $this->resolve_cloned_sites( $clone_action, $fs_instances );
557
+ }
558
+
559
+ /**
560
+ * @author Leo Fajard (@leorw)
561
+ * @since 2.5.0
562
+ *
563
+ * @return string|null
564
+ */
565
+ private function get_clone_resolution_action_from_config() {
566
+ if ( ! defined( 'FS__RESOLVE_CLONE_AS' ) ) {
567
+ return null;
568
+ }
569
+
570
+ if ( ! in_array(
571
+ FS__RESOLVE_CLONE_AS,
572
+ array(
573
+ self::OPTION_NEW_HOME,
574
+ self::OPTION_TEMPORARY_DUPLICATE,
575
+ self::OPTION_LONG_TERM_DUPLICATE,
576
+ )
577
+ ) ) {
578
+ return null;
579
+ }
580
+
581
+ return FS__RESOLVE_CLONE_AS;
582
  }
583
 
584
  /**
637
 
638
  $instance->switch_to_blog( $blog_id );
639
 
640
+ $current_url = untrailingslashit( Freemius::get_unfiltered_site_url( null, true ) );
641
  $current_install_url = is_object( $current_install ) ?
642
  fs_strip_url_protocol( untrailingslashit( $current_install->url ) ) :
643
  null;
667
  // If there's no expected install (or it couldn't be fetched) and the current install is a clone, try to resolve the clone automatically.
668
  $is_localhost = FS_Site::is_localhost_by_address( $current_url );
669
 
670
+ $resolved = $this->try_resolve_clone_automatically_by_instance( $instance, $current_url, $is_localhost, is_object( $network_subsite_clone_install ) );
671
 
672
  if ( ! $resolved && is_object( $network_subsite_clone_install ) ) {
673
  if ( empty( $this->get_clone_identification_timestamp() ) ) {
687
  }
688
 
689
  /**
690
+ * If a new install was created after creating a new subsite, its ID is stored in the blog-install map so that it can be recovered in case it's replaced with a clone install (e.g., when the newly created subsite is a clone). The IDs of the clone subsites that were created while not running this version of the SDK or a higher version will also be stored in the said map so that the clone manager can also try to resolve them later on.
691
  *
692
  * @author Leo Fajardo (@leorw)
693
  * @since 2.5.0
695
  * @param int $blog_id
696
  * @param FS_Site $site
697
  */
698
+ function store_blog_install_info( $blog_id, $site = null ) {
699
  $new_blog_install_map = $this->new_blog_install_map;
700
 
701
  if (
740
  private function try_automatic_resolution() {
741
  $this->_logger->entrance();
742
 
743
+ $current_url = untrailingslashit( Freemius::get_unfiltered_site_url( null, true ) );
744
  $is_localhost = FS_Site::is_localhost_by_address( $current_url );
745
 
746
  $require_manual_resolution = false;
756
  continue;
757
  }
758
 
759
+ if ( ! $this->try_resolve_clone_automatically_by_instance( $instance, $current_url, $is_localhost ) ) {
760
  $require_manual_resolution = true;
761
  }
762
  }
798
  ) );
799
  }
800
 
801
+ $result = $this->resolve_cloned_sites( $clone_action );
 
 
 
 
 
 
 
 
 
 
 
 
802
 
803
  Freemius::shoot_ajax_success( $result );
804
  }
807
  * @author Leo Fajardo (@leorw)
808
  * @since 2.5.0
809
  *
810
+ * @param string $clone_action
811
+ * @param Freemius[] $fs_instances
812
+ *
813
+ * @return array
814
  */
815
+ private function resolve_cloned_sites( $clone_action, $fs_instances = array() ) {
816
  $this->_logger->entrance();
817
 
818
+ $result = array();
 
 
819
 
820
+ if ( self::OPTION_TEMPORARY_DUPLICATE === $clone_action ) {
821
+ $this->store_temporary_duplicate_timestamp();
822
+ } else {
823
+ $instances_with_clone_count = 0;
824
+ $instance_with_error = null;
825
+ $has_error = false;
826
 
827
+ $instances = ( ! empty( $fs_instances ) ) ?
828
+ $fs_instances :
829
+ Freemius::_get_all_instances();
 
830
 
831
+ foreach ( $instances as $instance ) {
832
+ if ( ! $instance->is_registered() ) {
833
+ continue;
834
+ }
835
+
836
+ if ( ! $instance->is_clone() ) {
837
+ continue;
838
+ }
839
 
840
+ $instances_with_clone_count ++;
841
 
842
+ if ( self::OPTION_NEW_HOME === $clone_action ) {
843
+ $instance->sync_install( array( 'is_new_site' => true ), true );
844
+ } else {
845
+ $instance->_handle_long_term_duplicate();
846
 
847
+ if ( ! is_object( $instance->get_site() ) ) {
848
+ $has_error = true;
849
 
850
+ if ( ! is_object( $instance_with_error ) ) {
851
+ $instance_with_error = $instance;
852
+ }
853
  }
854
  }
855
  }
 
856
 
857
+ $redirect_url = '';
858
 
859
+ if (
860
+ 1 === $instances_with_clone_count &&
861
+ $has_error
862
+ ) {
863
+ $redirect_url = $instance_with_error->get_activation_url();
864
+ }
865
+
866
+ $result = ( array( 'redirect_url' => $redirect_url ) );
867
  }
868
 
869
+ if ( 'temporary_duplicate_license_activation' !== $clone_action ) {
870
+ $this->remove_clone_resolution_options_notice();
871
+ } else {
872
+ $this->remove_temporary_duplicate_notice();
873
+ }
874
+
875
+ return $result;
876
  }
877
 
878
  /**
974
  $product_ids,
975
  $product_titles,
976
  $site_urls,
977
+ Freemius::get_unfiltered_site_url(),
978
  ( count( $site_urls ) === count( $sites_with_license_urls ) ),
979
  ( count( $site_urls ) === $sites_with_premium_version_count ),
980
  $doc_url
1084
  continue;
1085
  }
1086
 
1087
+ $subsite_url = Freemius::get_unfiltered_site_url( $blog_id, true, true );
 
1088
 
1089
+ $has_clone = ( fs_strip_url_protocol( trailingslashit( $install->url ) ) !== $subsite_url );
1090
  }
1091
  }
1092
 
1283
  *
1284
  * @return string
1285
  */
1286
+ private function get_temporary_duplicate_admin_notice_string(
1287
+ $site_urls,
1288
+ $product_titles,
1289
+ $module_label
1290
+ ) {
1291
  $this->_logger->entrance();
1292
 
1293
  $temporary_duplicate_end_date = $this->get_temporary_duplicate_expiration_timestamp();
1294
  $temporary_duplicate_end_date = date( 'M j, Y', $temporary_duplicate_end_date );
1295
 
1296
+ $current_url = Freemius::get_unfiltered_site_url();
1297
  $current_site_link = sprintf(
1298
  '<b><a href="%s" target="_blank">%s</a></b>',
1299
  $current_url,
1490
  * @param string $message
1491
  * @param string|null $plugin_title
1492
  */
1493
+ function add_temporary_duplicate_sticky_notice(
1494
+ $product_ids,
1495
+ $message,
1496
+ $plugin_title = null
1497
+ ) {
1498
  $this->_logger->entrance();
1499
 
1500
  $this->_notices->add_sticky(
vendor/freemius/wordpress-sdk/includes/managers/class-fs-option-manager.php CHANGED
@@ -11,14 +11,11 @@
11
  }
12
 
13
  /**
14
- * 3-layer lazy options manager.
15
- * layer 3: Memory
16
- * layer 2: Cache (if there's any caching plugin and if WP_FS__DEBUG_SDK is FALSE)
17
- * layer 1: Database (options table). All options stored as one option record in the DB to reduce number of DB
18
- * queries.
19
  *
20
- * If load() is not explicitly called, starts as empty manager. Same thing about saving the data - you have to
21
- * explicitly call store().
22
  *
23
  * Class Freemius_Option_Manager
24
  */
@@ -157,59 +154,33 @@
157
  function load( $flush = false ) {
158
  $this->_logger->entrance();
159
 
160
- $option_name = $this->get_option_manager_name();
161
-
162
- if ( $flush || ! isset( $this->_options ) ) {
163
- if ( isset( $this->_options ) ) {
164
- // Clear prev options.
165
- $this->clear();
166
- }
167
-
168
- $cache_group = $this->get_cache_group();
169
-
170
- if ( WP_FS__DEBUG_SDK ) {
171
-
172
- // Don't use cache layer in DEBUG mode.
173
- $load_options = empty( $this->_options );
174
-
175
- } else {
176
-
177
- $this->_options = wp_cache_get(
178
- $option_name,
179
- $cache_group
180
- );
181
 
182
- $load_options = ( false === $this->_options );
183
- }
 
 
184
 
185
- $cached = true;
186
 
187
- if ( $load_options ) {
188
- if ( $this->_is_network_storage ) {
189
- $this->_options = get_site_option( $option_name );
190
- } else if ( $this->_blog_id > 0 ) {
191
- $this->_options = get_blog_option( $this->_blog_id, $option_name );
192
- } else {
193
- $this->_options = get_option( $option_name );
194
- }
195
 
196
- if ( is_string( $this->_options ) ) {
197
- $this->_options = json_decode( $this->_options );
198
- }
199
 
200
  // $this->_logger->info('get_option = ' . var_export($this->_options, true));
201
 
202
- if ( false === $this->_options ) {
203
- $this->clear();
204
- }
205
-
206
- $cached = false;
207
- }
208
-
209
- if ( ! WP_FS__DEBUG_SDK && ! $cached ) {
210
- // Set non encoded cache.
211
- wp_cache_set( $option_name, $this->_options, $cache_group );
212
- }
213
  }
214
  }
215
 
@@ -310,7 +281,7 @@
310
  /**
311
  * If it's an object, return a clone of the object, otherwise,
312
  * external changes of the object will actually change the value
313
- * of the object in the options manager which may lead to an unexpected
314
  * behaviour and data integrity when a store() call is triggered.
315
  *
316
  * Example:
@@ -436,10 +407,6 @@
436
  } else {
437
  update_option( $option_name, $this->_options, $this->_autoload );
438
  }
439
-
440
- if ( ! WP_FS__DEBUG_SDK ) {
441
- wp_cache_set( $option_name, $this->_options, $this->get_cache_group() );
442
- }
443
  }
444
 
445
  /**
@@ -499,23 +466,5 @@
499
  return $this->_id;
500
  }
501
 
502
- /**
503
- * @author Vova Feldman (@svovaf)
504
- * @since 2.0.0
505
- *
506
- * @return string
507
- */
508
- private function get_cache_group() {
509
- $group = WP_FS__SLUG;
510
-
511
- if ( $this->_is_network_storage ) {
512
- $group .= '_ms';
513
- } else if ( $this->_blog_id > 0 ) {
514
- $group .= "_s{$this->_blog_id}";
515
- }
516
-
517
- return $group;
518
- }
519
-
520
  #endregion
521
  }
11
  }
12
 
13
  /**
14
+ * 2-layer lazy options manager.
15
+ * layer 2: Memory
16
+ * layer 1: Database (options table). All options stored as one option record in the DB to reduce number of DB queries.
 
 
17
  *
18
+ * If load() is not explicitly called, starts as empty manager. Same thing about saving the data - you have to explicitly call store().
 
19
  *
20
  * Class Freemius_Option_Manager
21
  */
154
  function load( $flush = false ) {
155
  $this->_logger->entrance();
156
 
157
+ if ( ! $flush && isset( $this->_options ) ) {
158
+ return;
159
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
160
 
161
+ if ( isset( $this->_options ) ) {
162
+ // Clear prev options.
163
+ $this->clear();
164
+ }
165
 
166
+ $option_name = $this->get_option_manager_name();
167
 
168
+ if ( $this->_is_network_storage ) {
169
+ $this->_options = get_site_option( $option_name );
170
+ } else if ( $this->_blog_id > 0 ) {
171
+ $this->_options = get_blog_option( $this->_blog_id, $option_name );
172
+ } else {
173
+ $this->_options = get_option( $option_name );
174
+ }
 
175
 
176
+ if ( is_string( $this->_options ) ) {
177
+ $this->_options = json_decode( $this->_options );
178
+ }
179
 
180
  // $this->_logger->info('get_option = ' . var_export($this->_options, true));
181
 
182
+ if ( false === $this->_options ) {
183
+ $this->clear();
 
 
 
 
 
 
 
 
 
184
  }
185
  }
186
 
281
  /**
282
  * If it's an object, return a clone of the object, otherwise,
283
  * external changes of the object will actually change the value
284
+ * of the object in the option manager which may lead to an unexpected
285
  * behaviour and data integrity when a store() call is triggered.
286
  *
287
  * Example:
407
  } else {
408
  update_option( $option_name, $this->_options, $this->_autoload );
409
  }
 
 
 
 
410
  }
411
 
412
  /**
466
  return $this->_id;
467
  }
468
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
469
  #endregion
470
  }
vendor/freemius/wordpress-sdk/includes/sdk/FreemiusWordPress.php CHANGED
@@ -305,6 +305,8 @@
305
  * @return mixed
306
  */
307
  private static function ExecuteRequest( $pUrl, &$pWPRemoteArgs ) {
 
 
308
  $start = microtime( true );
309
 
310
  $response = wp_remote_request( $pUrl, $pWPRemoteArgs );
@@ -327,7 +329,7 @@
327
  $response['body'] :
328
  json_encode( $response->get_error_messages() ),
329
  'code' => ! $is_http_error ? $response['response']['code'] : null,
330
- 'backtrace' => debug_backtrace(),
331
  );
332
  }
333
 
305
  * @return mixed
306
  */
307
  private static function ExecuteRequest( $pUrl, &$pWPRemoteArgs ) {
308
+ $bt = debug_backtrace();
309
+
310
  $start = microtime( true );
311
 
312
  $response = wp_remote_request( $pUrl, $pWPRemoteArgs );
329
  $response['body'] :
330
  json_encode( $response->get_error_messages() ),
331
  'code' => ! $is_http_error ? $response['response']['code'] : null,
332
+ 'backtrace' => $bt,
333
  );
334
  }
335
 
vendor/freemius/wordpress-sdk/start.php CHANGED
@@ -15,7 +15,7 @@
15
  *
16
  * @var string
17
  */
18
- $this_sdk_version = '2.5.0.11';
19
 
20
  #region SDK Selection Logic --------------------------------------------------------------------
21
 
@@ -68,7 +68,11 @@
68
 
69
  if ( ! isset( $fs_active_plugins ) ) {
70
  // Load all Freemius powered active plugins.
71
- $fs_active_plugins = get_option( 'fs_active_plugins', new stdClass() );
 
 
 
 
72
 
73
  if ( ! isset( $fs_active_plugins->plugins ) ) {
74
  $fs_active_plugins->plugins = array();
15
  *
16
  * @var string
17
  */
18
+ $this_sdk_version = '2.5.0.18';
19
 
20
  #region SDK Selection Logic --------------------------------------------------------------------
21
 
68
 
69
  if ( ! isset( $fs_active_plugins ) ) {
70
  // Load all Freemius powered active plugins.
71
+ $fs_active_plugins = get_option( 'fs_active_plugins' );
72
+
73
+ if ( ! is_object( $fs_active_plugins ) ) {
74
+ $fs_active_plugins = new stdClass();
75
+ }
76
 
77
  if ( ! isset( $fs_active_plugins->plugins ) ) {
78
  $fs_active_plugins->plugins = array();
vendor/freemius/wordpress-sdk/templates/account.php CHANGED
@@ -59,6 +59,11 @@
59
  $show_upgrade = ( ! $is_whitelabeled && $has_paid_plan && ! $is_paying && ! $is_paid_trial );
60
  $trial_plan = $fs->get_trial_plan();
61
 
 
 
 
 
 
62
  if ( $has_paid_plan ) {
63
  $fs->_add_license_activation_dialog_box();
64
  }
@@ -243,6 +248,14 @@
243
  $addons_to_show = array_unique( array_merge( $installed_addons_ids, $account_addons ) );
244
 
245
  $is_active_bundle_subscription = ( is_object( $bundle_subscription ) && $bundle_subscription->is_active() );
 
 
 
 
 
 
 
 
246
  ?>
247
  <div class="wrap fs-section">
248
  <?php if ( ! $has_tabs && ! $fs->apply_filters( 'hide_account_tabs', false ) ) : ?>
@@ -283,24 +296,19 @@
283
  <li>&nbsp;&bull;&nbsp;</li>
284
  <?php endif ?>
285
  <?php if ( $show_billing ) : ?>
286
- <li><a href="#fs_billing"><i class="dashicons dashicons-portfolio"></i> <?php fs_esc_html_echo_inline( 'Billing & Invoices', 'billing-invoices', $slug ) ?></li>
287
  <li>&nbsp;&bull;&nbsp;</li>
288
  <?php endif ?>
289
  <?php if ( ! $is_whitelabeled ) : ?>
290
  <?php if ( ! $is_paying ) : ?>
291
  <li>
292
- <form action="<?php echo $fs->_get_admin_page_url( 'account' ) ?>" method="POST">
293
- <input type="hidden" name="fs_action" value="delete_account">
294
- <?php wp_nonce_field( 'delete_account' ) ?>
295
- <a class="fs-delete-account" href="#" onclick="if (confirm('<?php
296
- if ( $is_active_subscription ) {
297
- echo esc_attr( sprintf( fs_text_inline( 'Deleting the account will automatically deactivate your %s plan license so you can use it on other sites. If you want to terminate the recurring payments as well, click the "Cancel" button, and first "Downgrade" your account. Are you sure you would like to continue with the deletion?', 'delete-account-x-confirm', $slug ), $plan->title ) );
298
- } else {
299
- echo esc_attr( sprintf( fs_text_inline( 'Deletion is not temporary. Only delete if you no longer want to use this %s anymore. Are you sure you would like to continue with the deletion?', 'delete-account-confirm', $slug ), $fs->get_module_label( true ) ) );
300
- }
301
- ?>')) this.parentNode.submit(); return false;"><i
302
- class="dashicons dashicons-no"></i> <?php fs_esc_html_echo_inline( 'Delete Account', 'delete-account', $slug ) ?></a>
303
- </form>
304
  </li>
305
  <li>&nbsp;&bull;&nbsp;</li>
306
  <?php endif ?>
@@ -339,7 +347,7 @@
339
  </li>
340
  <li>&nbsp;&bull;&nbsp;</li>
341
  <?php endif ?>
342
- <?php if ( ! $fs->is_single_plan() ) : ?>
343
  <li>
344
  <a href="<?php echo $fs->get_upgrade_url() ?>"><i
345
  class="dashicons dashicons-grid-view"></i> <?php echo esc_html( $change_plan_text ) ?></a>
@@ -444,7 +452,7 @@
444
  'value' => $fs->get_plugin_version()
445
  );
446
 
447
- if ( ! fs_is_network_admin() && $is_premium && ! $is_whitelabeled ) {
448
  $profile[] = array(
449
  'id' => 'beta_program',
450
  'title' => '',
@@ -546,15 +554,13 @@
546
  <?php endif ?>
547
  <?php if ( ! $is_whitelabeled ) : ?>
548
  <div class="button-group">
549
- <?php $available_license = $fs->is_free_plan() && ! fs_is_network_admin() ? $fs->_get_available_premium_license( $site->is_localhost() ) : false ?>
550
  <?php if ( is_object( $available_license ) ) : ?>
551
- <?php $premium_plan = $fs->_get_plan_by_id( $available_license->plan_id ) ?>
552
  <?php
553
  $view_params = array(
554
  'freemius' => $fs,
555
  'slug' => $slug,
556
  'license' => $available_license,
557
- 'plan' => $premium_plan,
558
  'is_localhost' => $site->is_localhost(),
559
  'install_id' => $site->id,
560
  'class' => 'button-primary',
@@ -571,7 +577,7 @@
571
  <input type="hidden" name="fs_action"
572
  value="<?php echo $fs->get_unique_affix() ?>_sync_license">
573
  <?php wp_nonce_field( $fs->get_unique_affix() . '_sync_license' ) ?>
574
- <?php if ( $show_upgrade || ! $fs->is_single_plan() ) : ?>
575
  <a href="<?php echo $fs->get_upgrade_url() ?>"
576
  class="button<?php
577
  echo $show_upgrade ?
@@ -948,7 +954,7 @@
948
 
949
  if ( ! isChecked || confirm( '<?php echo $confirmation_message ?>' ) ) {
950
  $.ajax( {
951
- url : ajaxurl,
952
  method: 'POST',
953
  data : {
954
  action : '<?php echo $fs->get_ajax_action( 'set_beta_mode' ) ?>',
@@ -1091,7 +1097,7 @@
1091
  var $toggleLink = $( this );
1092
 
1093
  $.ajax( {
1094
- url : ajaxurl,
1095
  method: 'POST',
1096
  data : {
1097
  action : '<?php echo $fs->get_ajax_action( 'toggle_whitelabel_mode' ) ?>',
59
  $show_upgrade = ( ! $is_whitelabeled && $has_paid_plan && ! $is_paying && ! $is_paid_trial );
60
  $trial_plan = $fs->get_trial_plan();
61
 
62
+ $is_plan_change_supported = (
63
+ ! $fs->is_single_plan() &&
64
+ ! $fs->apply_filters( 'hide_plan_change', false )
65
+ );
66
+
67
  if ( $has_paid_plan ) {
68
  $fs->_add_license_activation_dialog_box();
69
  }
248
  $addons_to_show = array_unique( array_merge( $installed_addons_ids, $account_addons ) );
249
 
250
  $is_active_bundle_subscription = ( is_object( $bundle_subscription ) && $bundle_subscription->is_active() );
251
+
252
+ $available_license = ( $fs->is_free_plan() && ! fs_is_network_admin() ) ?
253
+ $fs->_get_available_premium_license( $site->is_localhost() ) :
254
+ null;
255
+
256
+ $available_license_paid_plan = is_object( $available_license ) ?
257
+ $fs->_get_plan_by_id( $available_license->plan_id ) :
258
+ null;
259
  ?>
260
  <div class="wrap fs-section">
261
  <?php if ( ! $has_tabs && ! $fs->apply_filters( 'hide_account_tabs', false ) ) : ?>
296
  <li>&nbsp;&bull;&nbsp;</li>
297
  <?php endif ?>
298
  <?php if ( $show_billing ) : ?>
299
+ <li><a href="#fs_billing"><i class="dashicons dashicons-portfolio"></i> <?php fs_esc_html_echo_inline( 'Billing & Invoices', 'billing-invoices', $slug ) ?></a></li>
300
  <li>&nbsp;&bull;&nbsp;</li>
301
  <?php endif ?>
302
  <?php if ( ! $is_whitelabeled ) : ?>
303
  <?php if ( ! $is_paying ) : ?>
304
  <li>
305
+ <?php
306
+ $view_params = array(
307
+ 'freemius' => $fs,
308
+ 'license' => $available_license,
309
+ 'license_paid_plan' => $available_license_paid_plan,
310
+ );
311
+ fs_require_template( 'account/partials/disconnect-button.php', $view_params ); ?>
 
 
 
 
 
312
  </li>
313
  <li>&nbsp;&bull;&nbsp;</li>
314
  <?php endif ?>
347
  </li>
348
  <li>&nbsp;&bull;&nbsp;</li>
349
  <?php endif ?>
350
+ <?php if ( $is_plan_change_supported ) : ?>
351
  <li>
352
  <a href="<?php echo $fs->get_upgrade_url() ?>"><i
353
  class="dashicons dashicons-grid-view"></i> <?php echo esc_html( $change_plan_text ) ?></a>
452
  'value' => $fs->get_plugin_version()
453
  );
454
 
455
+ if ( ! fs_is_network_admin() && $is_premium ) {
456
  $profile[] = array(
457
  'id' => 'beta_program',
458
  'title' => '',
554
  <?php endif ?>
555
  <?php if ( ! $is_whitelabeled ) : ?>
556
  <div class="button-group">
 
557
  <?php if ( is_object( $available_license ) ) : ?>
 
558
  <?php
559
  $view_params = array(
560
  'freemius' => $fs,
561
  'slug' => $slug,
562
  'license' => $available_license,
563
+ 'plan' => $available_license_paid_plan,
564
  'is_localhost' => $site->is_localhost(),
565
  'install_id' => $site->id,
566
  'class' => 'button-primary',
577
  <input type="hidden" name="fs_action"
578
  value="<?php echo $fs->get_unique_affix() ?>_sync_license">
579
  <?php wp_nonce_field( $fs->get_unique_affix() . '_sync_license' ) ?>
580
+ <?php if ( $show_upgrade || $is_plan_change_supported ) : ?>
581
  <a href="<?php echo $fs->get_upgrade_url() ?>"
582
  class="button<?php
583
  echo $show_upgrade ?
954
 
955
  if ( ! isChecked || confirm( '<?php echo $confirmation_message ?>' ) ) {
956
  $.ajax( {
957
+ url : <?php echo Freemius::ajax_url() ?>,
958
  method: 'POST',
959
  data : {
960
  action : '<?php echo $fs->get_ajax_action( 'set_beta_mode' ) ?>',
1097
  var $toggleLink = $( this );
1098
 
1099
  $.ajax( {
1100
+ url : <?php echo Freemius::ajax_url() ?>,
1101
  method: 'POST',
1102
  data : {
1103
  action : '<?php echo $fs->get_ajax_action( 'toggle_whitelabel_mode' ) ?>',
vendor/freemius/wordpress-sdk/templates/account/billing.php CHANGED
@@ -377,7 +377,7 @@
377
  });
378
 
379
  $.ajax({
380
- url : ajaxurl,
381
  method : 'POST',
382
  data : {
383
  action : '<?php echo $fs->get_ajax_action( 'update_billing' ) ?>',
377
  });
378
 
379
  $.ajax({
380
+ url : <?php echo Freemius::ajax_url() ?>,
381
  method : 'POST',
382
  data : {
383
  action : '<?php echo $fs->get_ajax_action( 'update_billing' ) ?>',
vendor/freemius/wordpress-sdk/templates/account/partials/disconnect-button.php ADDED
@@ -0,0 +1,104 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @package Freemius
4
+ * @copyright Copyright (c) 2016, Freemius, Inc.
5
+ * @license https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License Version 3
6
+ * @since 2.5.0
7
+ */
8
+
9
+ if ( ! defined( 'ABSPATH' ) ) {
10
+ exit;
11
+ }
12
+
13
+ /**
14
+ * @var array $VARS
15
+ * @var Freemius $fs
16
+ */
17
+ $fs = $VARS['freemius'];
18
+
19
+ /**
20
+ * @var FS_Plugin_License $license
21
+ */
22
+ $license = $VARS['license'];
23
+ /**
24
+ * @var FS_Plugin_Plan $license_paid_plan
25
+ */
26
+ $license_paid_plan = $VARS['license_paid_plan'];
27
+
28
+ $license_subscription = ( is_object( $license ) && is_object( $license_paid_plan ) ) ?
29
+ $fs->_get_subscription( $license->id ) :
30
+ null;
31
+
32
+ $has_active_subscription = (
33
+ is_object( $license_subscription ) &&
34
+ $license_subscription->is_active()
35
+ );
36
+
37
+ $button_id = "fs_disconnect_button_{$fs->get_id()}";
38
+
39
+ $website_link = sprintf( '<a href="#" tabindex="-1">%s</a>', fs_strip_url_protocol( untrailingslashit( Freemius::get_unfiltered_site_url() ) ) );
40
+ ?>
41
+ <script type="text/javascript">
42
+ // Wrap in a IFFE to prevent leaking global variables.
43
+ ( function( $ ) {
44
+ $( document ).ready( function() {
45
+ var $modal = $( '#fs_modal_delete_site' );
46
+
47
+ $( '#<?php echo $button_id ?>' ).on( 'click', function( e ) {
48
+ // Prevent the form being submitted.
49
+ e.preventDefault();
50
+
51
+ $( document.body ).append( $modal );
52
+ $modal.show();
53
+ } );
54
+
55
+ $modal.on( 'click', '.button-close', function ( evt ) {
56
+ $modal.hide();
57
+ } );
58
+
59
+ $modal.on( 'click', '.button-primary', function ( evt ) {
60
+ $( '#<?php echo $button_id ?>' ).closest( 'form' )[0].submit();
61
+ } );
62
+ } );
63
+ } )( jQuery );
64
+ </script>
65
+ <div id="fs_modal_delete_site" class="fs-modal active" style="display: none">
66
+ <div class="fs-modal-dialog">
67
+ <div class="fs-modal-header">
68
+ <h4><?php echo $fs->esc_html_inline( 'Disconnect', 'disconnect' ) ?></h4>
69
+ </div>
70
+ <div class="fs-modal-body">
71
+ <?php if ( ! is_object( $license ) ) : ?>
72
+ <p><?php echo
73
+ // translators: %1$s is replaced with the website's homepage address, %2$s is replaced with the plugin name.
74
+ sprintf( esc_html( $fs->get_text_inline( 'By disconnecting the website, previously shared diagnostic data about %1$s will be deleted and no longer visible to %2$s.', 'disconnect-intro-paid' ) ), $website_link, '<b>' . $fs->get_plugin_title() . '</b>' ) ?></p>
75
+ <?php else : ?>
76
+ <p><?php echo
77
+ // translators: %s is replaced with the website's homepage address.
78
+ sprintf( esc_html( $fs->get_text_inline( 'Disconnecting the website will permanently remove %s from your User Dashboard\'s account.', 'disconnect-intro-paid' ) ), $website_link ) ?></p>
79
+ <?php endif ?>
80
+
81
+ <?php if ( $has_active_subscription ) : ?>
82
+ <p><?php echo
83
+ // translators: %1$s is replaced by the paid plan name, %2$s is replaced with an anchor link with the text "User Dashboard".
84
+ sprintf( esc_html( $fs->get_text_inline( 'If you wish to cancel your %1$s plan\'s subscription instead, please navigate to the %2$s and cancel it there.', 'disconnect-subscription-disclaimer' ) ), $license_paid_plan->title, sprintf( '<a href="https://users.freemius.com" target="_blank" rel="noreferrer noopener nofollow">%s</a>', $fs->get_text_inline( 'User Dashboard', 'user-dashboard' ) )
85
+ ) ?></p>
86
+ <?php endif ?>
87
+
88
+ <p><?php echo esc_html( $fs->get_text_inline( 'Are you sure you would like to proceed with the disconnection?', 'disconnect-confirm' ) ) ?></p>
89
+ </div>
90
+ <div class="fs-modal-footer">
91
+ <button class="button button-primary<?php if ( is_object( $license ) ) : ?> warn<?php endif ?>" tabindex="2"><?php echo $fs->esc_html_inline( 'Yes', 'yes' ) . ' - ' . $fs->esc_html_inline( 'Disconnect', 'disconnect' ) ?></button>
92
+ <button class="button button-secondary button-close" tabindex="1"><?php echo esc_html( $fs->get_text_inline( 'Cancel', 'cancel' ) ) ?></button>
93
+ </div>
94
+ </div>
95
+ </div>
96
+ <form action="<?php echo esc_attr( $fs->_get_admin_page_url( 'account' ) ); ?>" method="POST">
97
+ <input type="hidden" name="fs_action" value="delete_account">
98
+ <?php wp_nonce_field( 'delete_account' ) ?>
99
+
100
+ <a id="<?php echo $button_id ?>" href="#" class="fs-button-inline">
101
+ <i class="dashicons dashicons-no"></i>
102
+ <?php echo $fs->esc_html_inline( 'Disconnect', 'disconnect' ) ?>
103
+ </a>
104
+ </form>
vendor/freemius/wordpress-sdk/templates/auto-installation.php CHANGED
@@ -164,7 +164,7 @@
164
  }
165
 
166
  $.ajax({
167
- url : ajaxurl,
168
  method : 'POST',
169
  data : data,
170
  success: function (resultObj) {
164
  }
165
 
166
  $.ajax({
167
+ url : <?php echo Freemius::ajax_url() ?>,
168
  method : 'POST',
169
  data : data,
170
  success: function (resultObj) {
vendor/freemius/wordpress-sdk/templates/connect.php CHANGED
@@ -41,7 +41,7 @@
41
  $first_name = $current_user->nickname;
42
  }
43
 
44
- $site_url = get_site_url();
45
  $protocol_pos = strpos( $site_url, '://' );
46
  if ( false !== $protocol_pos ) {
47
  $site_url = substr( $site_url, $protocol_pos + 3 );
@@ -824,7 +824,6 @@
824
  url : $this.find( '.url' ).val(),
825
  title : $this.find( '.title' ).val(),
826
  language: $this.find( '.language' ).val(),
827
- charset : $this.find( '.charset' ).val(),
828
  blog_id : $this.find( '.blog-id' ).find( 'span' ).text()
829
  };
830
 
@@ -852,7 +851,7 @@
852
  * @since 1.2.1.5
853
  */
854
  $.ajax({
855
- url : ajaxurl,
856
  method : 'POST',
857
  data : data,
858
  success: function (result) {
@@ -1037,7 +1036,7 @@
1037
  $primaryCta.html('<?php fs_esc_js_echo_inline( 'Please wait', 'please-wait', $slug ) ?>...');
1038
 
1039
  $.ajax({
1040
- url : ajaxurl,
1041
  method : 'POST',
1042
  data : {
1043
  action : '<?php echo $fs->get_ajax_action( 'fetch_is_marketing_required_flag_value' ) ?>',
@@ -1067,4 +1066,4 @@
1067
 
1068
  //endregion
1069
  })(jQuery);
1070
- </script>
41
  $first_name = $current_user->nickname;
42
  }
43
 
44
+ $site_url = Freemius::get_unfiltered_site_url();
45
  $protocol_pos = strpos( $site_url, '://' );
46
  if ( false !== $protocol_pos ) {
47
  $site_url = substr( $site_url, $protocol_pos + 3 );
824
  url : $this.find( '.url' ).val(),
825
  title : $this.find( '.title' ).val(),
826
  language: $this.find( '.language' ).val(),
 
827
  blog_id : $this.find( '.blog-id' ).find( 'span' ).text()
828
  };
829
 
851
  * @since 1.2.1.5
852
  */
853
  $.ajax({
854
+ url : <?php echo Freemius::ajax_url() ?>,
855
  method : 'POST',
856
  data : data,
857
  success: function (result) {
1036
  $primaryCta.html('<?php fs_esc_js_echo_inline( 'Please wait', 'please-wait', $slug ) ?>...');
1037
 
1038
  $.ajax({
1039
+ url : <?php echo Freemius::ajax_url() ?>,
1040
  method : 'POST',
1041
  data : {
1042
  action : '<?php echo $fs->get_ajax_action( 'fetch_is_marketing_required_flag_value' ) ?>',
1066
 
1067
  //endregion
1068
  })(jQuery);
1069
+ </script>
vendor/freemius/wordpress-sdk/templates/contact.php CHANGED
@@ -69,7 +69,7 @@
69
  $query_params = array_merge( $_GET, array_merge( $context_params, array(
70
  'plugin_version' => $fs->get_plugin_version(),
71
  'wp_login_url' => wp_login_url(),
72
- 'site_url' => get_site_url(),
73
  // 'wp_admin_css' => get_bloginfo('wpurl') . "/wp-admin/load-styles.php?c=1&load=buttons,wp-admin,dashicons",
74
  ) ) );
75
 
69
  $query_params = array_merge( $_GET, array_merge( $context_params, array(
70
  'plugin_version' => $fs->get_plugin_version(),
71
  'wp_login_url' => wp_login_url(),
72
+ 'site_url' => Freemius::get_unfiltered_site_url(),
73
  // 'wp_admin_css' => get_bloginfo('wpurl') . "/wp-admin/load-styles.php?c=1&load=buttons,wp-admin,dashicons",
74
  ) ) );
75
 
vendor/freemius/wordpress-sdk/templates/debug.php CHANGED
@@ -35,7 +35,7 @@
35
  .toggleClass( 'fs-on' )
36
  .toggleClass( 'fs-off' );
37
 
38
- $.post( ajaxurl, {
39
  action: 'fs_toggle_debug_mode',
40
  // As such we don't need to use `wp_json_encode` method but using it to follow wp.org guideline.
41
  _wpnonce : <?php echo wp_json_encode( wp_create_nonce( 'fs_toggle_debug_mode' ) ); ?>,
@@ -121,7 +121,7 @@
121
  var optionName = prompt('Please enter the option name:');
122
 
123
  if (optionName) {
124
- $.post(ajaxurl, {
125
  action : 'fs_get_db_option',
126
  // As such we don't need to use `wp_json_encode` method but using it to follow wp.org guideline.
127
  _wpnonce : <?php echo wp_json_encode( wp_create_nonce( 'fs_get_db_option' ) ); ?>,
@@ -142,7 +142,7 @@
142
  var optionValue = prompt('Please enter the option value:');
143
 
144
  if (optionValue) {
145
- $.post(ajaxurl, {
146
  action : 'fs_set_db_option',
147
  // As such we don't need to use `wp_json_encode` method but using it to follow wp.org guideline.
148
  _wpnonce : <?php echo wp_json_encode( wp_create_nonce( 'fs_set_db_option' ) ); ?>,
@@ -185,6 +185,10 @@
185
  'key' => 'WP_FS__DIR',
186
  'val' => WP_FS__DIR,
187
  ),
 
 
 
 
188
  )
189
  ?>
190
  <br>
@@ -740,7 +744,7 @@
740
  offset = 0;
741
  }
742
 
743
- $.post(ajaxurl, {
744
  action : 'fs_get_debug_log',
745
  // As such we don't need to use `wp_json_encode` method but using it to follow wp.org guideline.
746
  _wpnonce : <?php echo wp_json_encode( wp_create_nonce( 'fs_get_debug_log' ) ); ?>,
35
  .toggleClass( 'fs-on' )
36
  .toggleClass( 'fs-off' );
37
 
38
+ $.post( <?php echo Freemius::ajax_url() ?>, {
39
  action: 'fs_toggle_debug_mode',
40
  // As such we don't need to use `wp_json_encode` method but using it to follow wp.org guideline.
41
  _wpnonce : <?php echo wp_json_encode( wp_create_nonce( 'fs_toggle_debug_mode' ) ); ?>,
121
  var optionName = prompt('Please enter the option name:');
122
 
123
  if (optionName) {
124
+ $.post(<?php echo Freemius::ajax_url() ?>, {
125
  action : 'fs_get_db_option',
126
  // As such we don't need to use `wp_json_encode` method but using it to follow wp.org guideline.
127
  _wpnonce : <?php echo wp_json_encode( wp_create_nonce( 'fs_get_db_option' ) ); ?>,
142
  var optionValue = prompt('Please enter the option value:');
143
 
144
  if (optionValue) {
145
+ $.post(<?php echo Freemius::ajax_url() ?>, {
146
  action : 'fs_set_db_option',
147
  // As such we don't need to use `wp_json_encode` method but using it to follow wp.org guideline.
148
  _wpnonce : <?php echo wp_json_encode( wp_create_nonce( 'fs_set_db_option' ) ); ?>,
185
  'key' => 'WP_FS__DIR',
186
  'val' => WP_FS__DIR,
187
  ),
188
+ array(
189
+ 'key' => 'wp_using_ext_object_cache()',
190
+ 'val' => wp_using_ext_object_cache() ? 'true' : 'false',
191
+ ),
192
  )
193
  ?>
194
  <br>
744
  offset = 0;
745
  }
746
 
747
+ $.post(<?php echo Freemius::ajax_url() ?>, {
748
  action : 'fs_get_debug_log',
749
  // As such we don't need to use `wp_json_encode` method but using it to follow wp.org guideline.
750
  _wpnonce : <?php echo wp_json_encode( wp_create_nonce( 'fs_get_debug_log' ) ); ?>,
vendor/freemius/wordpress-sdk/templates/firewall-issues-js.php CHANGED
@@ -48,8 +48,7 @@
48
 
49
  $( this ).css({'cursor': 'wait'});
50
 
51
- // since 2.8 ajaxurl is always defined in the admin header and points to admin-ajax.php
52
- $.post( ajaxurl, data, function( response ) {
53
  if ( 1 == response ) {
54
  // Refresh page on success.
55
  location.reload();
48
 
49
  $( this ).css({'cursor': 'wait'});
50
 
51
+ $.post( <?php echo Freemius::ajax_url() ?>, data, function( response ) {
 
52
  if ( 1 == response ) {
53
  // Refresh page on success.
54
  location.reload();
vendor/freemius/wordpress-sdk/templates/forms/affiliation.php CHANGED
@@ -72,7 +72,7 @@
72
  $current_user = Freemius::_get_current_wp_user();
73
  $full_name = trim( $current_user->user_firstname . ' ' . $current_user->user_lastname );
74
  $email_address = $current_user->user_email;
75
- $domain = fs_strip_url_protocol( get_site_url() );
76
  }
77
 
78
  $affiliate_tracking = 30;
@@ -366,7 +366,7 @@
366
  }
367
 
368
  $.ajax({
369
- url : ajaxurl,
370
  method : 'POST',
371
  data : {
372
  action : '<?php echo $fs->get_ajax_action( 'submit_affiliate_application' ) ?>',
72
  $current_user = Freemius::_get_current_wp_user();
73
  $full_name = trim( $current_user->user_firstname . ' ' . $current_user->user_lastname );
74
  $email_address = $current_user->user_email;
75
+ $domain = Freemius::get_unfiltered_site_url( null, true );
76
  }
77
 
78
  $affiliate_tracking = 30;
366
  }
367
 
368
  $.ajax({
369
+ url : <?php echo Freemius::ajax_url() ?>,
370
  method : 'POST',
371
  data : {
372
  action : '<?php echo $fs->get_ajax_action( 'submit_affiliate_application' ) ?>',
vendor/freemius/wordpress-sdk/templates/forms/data-debug-mode.php CHANGED
@@ -140,7 +140,7 @@ HTML;
140
  };
141
 
142
  $.ajax( {
143
- url : ajaxurl,
144
  method : 'POST',
145
  data : data,
146
  beforeSend: function () {
140
  };
141
 
142
  $.ajax( {
143
+ url : <?php echo Freemius::ajax_url() ?>,
144
  method : 'POST',
145
  data : data,
146
  beforeSend: function () {
vendor/freemius/wordpress-sdk/templates/forms/deactivation/form.php CHANGED
@@ -180,7 +180,7 @@ HTML;
180
  ?>
181
 
182
  $.ajax({
183
- url : ajaxurl,
184
  method : 'POST',
185
  data : {
186
  action : '<?php echo $fs->get_ajax_action( 'cancel_subscription_or_trial' ) ?>',
@@ -347,7 +347,7 @@ HTML;
347
  window.location.href = redirectLink;
348
  } else {
349
  $.ajax({
350
- url : ajaxurl,
351
  method : 'POST',
352
  data : {
353
  action : '<?php echo $fs->get_ajax_action( 'delete_theme_update_data' ) ?>',
@@ -366,15 +366,15 @@ HTML;
366
  return;
367
  }
368
 
369
- var snoozePeriod = 0;
370
-
371
- if ( <?php echo Freemius::REASON_TEMPORARY_DEACTIVATION ?> == selectedReasonID ) {
 
372
  snoozePeriod = parseInt($feedbackSnooze.find('select').val(), 10);
373
  }
374
-
375
 
376
  $.ajax({
377
- url : ajaxurl,
378
  method : 'POST',
379
  data : {
380
  action : '<?php echo $fs->get_ajax_action( 'submit_uninstall_reason' ) ?>',
180
  ?>
181
 
182
  $.ajax({
183
+ url : <?php echo Freemius::ajax_url() ?>,
184
  method : 'POST',
185
  data : {
186
  action : '<?php echo $fs->get_ajax_action( 'cancel_subscription_or_trial' ) ?>',
347
  window.location.href = redirectLink;
348
  } else {
349
  $.ajax({
350
+ url : <?php echo Freemius::ajax_url() ?>,
351
  method : 'POST',
352
  data : {
353
  action : '<?php echo $fs->get_ajax_action( 'delete_theme_update_data' ) ?>',
366
  return;
367
  }
368
 
369
+ var snoozePeriod = 0,
370
+ shouldSnooze = $feedbackSnooze.find( '.feedback-from-snooze-checkbox' ).is( ':checked' );
371
+
372
+ if ( shouldSnooze && <?php echo Freemius::REASON_TEMPORARY_DEACTIVATION ?> == selectedReasonID ) {
373
  snoozePeriod = parseInt($feedbackSnooze.find('select').val(), 10);
374
  }
 
375
 
376
  $.ajax({
377
+ url : <?php echo Freemius::ajax_url() ?>,
378
  method : 'POST',
379
  data : {
380
  action : '<?php echo $fs->get_ajax_action( 'submit_uninstall_reason' ) ?>',
vendor/freemius/wordpress-sdk/templates/forms/email-address-update.php CHANGED
@@ -185,7 +185,7 @@
185
  }
186
 
187
  $.ajax( {
188
- url : ajaxurl,
189
  method : 'POST',
190
  data : {
191
  action : '<?php echo $fs->get_ajax_action( 'update_email_address' ) ?>',
185
  }
186
 
187
  $.ajax( {
188
+ url : <?php echo Freemius::ajax_url() ?>,
189
  method : 'POST',
190
  data : {
191
  action : '<?php echo $fs->get_ajax_action( 'update_email_address' ) ?>',
vendor/freemius/wordpress-sdk/templates/forms/license-activation.php CHANGED
@@ -369,7 +369,7 @@ HTML;
369
  $activateLicenseButton.html( '<?php fs_esc_js_echo_inline( 'Please wait', 'please-wait', $slug ) ?>...' );
370
 
371
  $.ajax( {
372
- url : ajaxurl,
373
  method : 'POST',
374
  data : {
375
  action : '<?php echo $fs->get_ajax_action( 'fetch_is_marketing_required_flag_value' ) ?>',
@@ -617,7 +617,6 @@ HTML;
617
  url : $this.find( '.url' ).val(),
618
  title : $this.find( '.title' ).val(),
619
  language: $this.find( '.language' ).val(),
620
- charset : $this.find( '.charset' ).val(),
621
  blog_id : $this.find( '.blog-id' ).find( 'span' ).text()
622
  };
623
 
@@ -635,7 +634,7 @@ HTML;
635
  }
636
 
637
  $.ajax({
638
- url: ajaxurl,
639
  method: 'POST',
640
  data: data,
641
  beforeSend: function () {
@@ -895,4 +894,4 @@ HTML;
895
  }
896
  });
897
  })( jQuery );
898
- </script>
369
  $activateLicenseButton.html( '<?php fs_esc_js_echo_inline( 'Please wait', 'please-wait', $slug ) ?>...' );
370
 
371
  $.ajax( {
372
+ url : <?php echo Freemius::ajax_url() ?>,
373
  method : 'POST',
374
  data : {
375
  action : '<?php echo $fs->get_ajax_action( 'fetch_is_marketing_required_flag_value' ) ?>',
617
  url : $this.find( '.url' ).val(),
618
  title : $this.find( '.title' ).val(),
619
  language: $this.find( '.language' ).val(),
 
620
  blog_id : $this.find( '.blog-id' ).find( 'span' ).text()
621
  };
622
 
634
  }
635
 
636
  $.ajax({
637
+ url: <?php echo Freemius::ajax_url() ?>,
638
  method: 'POST',
639
  data: data,
640
  beforeSend: function () {
894
  }
895
  });
896
  })( jQuery );
897
+ </script>
vendor/freemius/wordpress-sdk/templates/forms/optout.php CHANGED
@@ -182,7 +182,7 @@
182
  var $actionLink = $( actionLinkSelector );
183
 
184
  $.ajax({
185
- url: ajaxurl,
186
  method: 'POST',
187
  data: {
188
  action : ( 'stop_tracking' == action ?
@@ -246,7 +246,7 @@
246
  $switchFeedback.html( '<i class="fs-ajax-spinner"></i>' );
247
 
248
  $.ajax({
249
- url: ajaxurl,
250
  method: 'POST',
251
  data: {
252
  action : '<?php echo $fs->get_ajax_action( 'update_tracking_permission' ) ?>',
182
  var $actionLink = $( actionLinkSelector );
183
 
184
  $.ajax({
185
+ url: <?php echo Freemius::ajax_url() ?>,
186
  method: 'POST',
187
  data: {
188
  action : ( 'stop_tracking' == action ?
246
  $switchFeedback.html( '<i class="fs-ajax-spinner"></i>' );
247
 
248
  $.ajax({
249
+ url: <?php echo Freemius::ajax_url() ?>,
250
  method: 'POST',
251
  data: {
252
  action : '<?php echo $fs->get_ajax_action( 'update_tracking_permission' ) ?>',
vendor/freemius/wordpress-sdk/templates/forms/resend-key.php CHANGED
@@ -145,7 +145,7 @@ HTML;
145
  }
146
 
147
  $.ajax({
148
- url : ajaxurl,
149
  method : 'POST',
150
  data : {
151
  action : '<?php echo $fs->get_ajax_action( 'resend_license_key' ) ?>',
145
  }
146
 
147
  $.ajax({
148
+ url : <?php echo Freemius::ajax_url() ?>,
149
  method : 'POST',
150
  data : {
151
  action : '<?php echo $fs->get_ajax_action( 'resend_license_key' ) ?>',
vendor/freemius/wordpress-sdk/templates/forms/trial-start.php CHANGED
@@ -80,7 +80,7 @@ HTML;
80
  var $button = $(this);
81
 
82
  $.ajax({
83
- url : ajaxurl,
84
  method : 'POST',
85
  data : {
86
  action : '<?php echo $fs->get_ajax_action( 'start_trial' ) ?>',
80
  var $button = $(this);
81
 
82
  $.ajax({
83
+ url : <?php echo Freemius::ajax_url() ?>,
84
  method : 'POST',
85
  data : {
86
  action : '<?php echo $fs->get_ajax_action( 'start_trial' ) ?>',
vendor/freemius/wordpress-sdk/templates/forms/user-change.php CHANGED
@@ -194,7 +194,7 @@ HTML;
194
  disableUserChangeButton();
195
 
196
  $.ajax( {
197
- url : ajaxurl,
198
  method : 'POST',
199
  data : {
200
  action : '<?php echo $fs->get_ajax_action( 'change_user' ) ?>',
194
  disableUserChangeButton();
195
 
196
  $.ajax( {
197
+ url : <?php echo Freemius::ajax_url() ?>,
198
  method : 'POST',
199
  data : {
200
  action : '<?php echo $fs->get_ajax_action( 'change_user' ) ?>',
vendor/freemius/wordpress-sdk/templates/gdpr-optin-js.php CHANGED
@@ -38,7 +38,7 @@
38
  }
39
 
40
  $.ajax({
41
- url : ajaxurl + '?' + $.param({
42
  action : '<?php echo $fs->get_ajax_action( 'gdpr_optin_action' ) ?>',
43
  security : '<?php echo $fs->get_ajax_security( 'gdpr_optin_action' ) ?>',
44
  module_id: '<?php echo $fs->get_id() ?>'
38
  }
39
 
40
  $.ajax({
41
+ url : <?php echo Freemius::ajax_url() ?> + '?' + $.param({
42
  action : '<?php echo $fs->get_ajax_action( 'gdpr_optin_action' ) ?>',
43
  security : '<?php echo $fs->get_ajax_security( 'gdpr_optin_action' ) ?>',
44
  module_id: '<?php echo $fs->get_id() ?>'
vendor/freemius/wordpress-sdk/templates/partials/network-activation.php CHANGED
@@ -58,7 +58,7 @@
58
  <div class="fs-sites-list-container">
59
  <table cellspacing="0">
60
  <tbody>
61
- <?php $site_props = array('uid', 'url', 'title', 'charset', 'language') ?>
62
  <?php foreach ( $sites as $site ) : ?>
63
  <tr<?php if ( ! empty( $site['license_id'] ) ) {
64
  echo ' data-license-id="' . $site['license_id'] . '"';
58
  <div class="fs-sites-list-container">
59
  <table cellspacing="0">
60
  <tbody>
61
+ <?php $site_props = array('uid', 'url', 'title', 'language') ?>
62
  <?php foreach ( $sites as $site ) : ?>
63
  <tr<?php if ( ! empty( $site['license_id'] ) ) {
64
  echo ' data-license-id="' . $site['license_id'] . '"';
vendor/freemius/wordpress-sdk/templates/sticky-admin-notice-js.php CHANGED
@@ -29,8 +29,7 @@
29
  message_id: id
30
  };
31
 
32
- // since 2.8 ajaxurl is always defined in the admin header and points to admin-ajax.php
33
- $.post( ajaxurl, data, function( response ) {
34
 
35
  });
36
 
29
  message_id: id
30
  };
31
 
32
+ $.post( <?php echo Freemius::ajax_url() ?>, data, function( response ) {
 
33
 
34
  });
35
 
vendor/freemius/wordpress-sdk/templates/tabs-capture-js.php CHANGED
@@ -45,7 +45,7 @@
45
  var tabsHtml = $('.wrap .nav-tab-wrapper').clone().wrap('<div>').parent().html();
46
 
47
  $.ajax({
48
- url : ajaxurl + '?' + $.param({
49
  action : '<?php echo $fs->get_ajax_action( 'store_tabs' ) ?>',
50
  security : '<?php echo $fs->get_ajax_security( 'store_tabs' ) ?>',
51
  module_id: '<?php echo $fs->get_id() ?>'
45
  var tabsHtml = $('.wrap .nav-tab-wrapper').clone().wrap('<div>').parent().html();
46
 
47
  $.ajax({
48
+ url : <?php echo Freemius::ajax_url() ?> + '?' + $.param({
49
  action : '<?php echo $fs->get_ajax_action( 'store_tabs' ) ?>',
50
  security : '<?php echo $fs->get_ajax_security( 'store_tabs' ) ?>',
51
  module_id: '<?php echo $fs->get_id() ?>'
wp-fail2ban.php CHANGED
@@ -4,7 +4,7 @@
4
  * Plugin URI: https://wp-fail2ban.com/
5
  * Description: Write a myriad of WordPress events to syslog for integration with fail2ban.
6
  * Text Domain: wp-fail2ban
7
- * Version: 4.4.0.6
8
  * Author: Charles Lecklider
9
  * Author URI: https://invis.net/
10
  * License: GPLv3
4
  * Plugin URI: https://wp-fail2ban.com/
5
  * Description: Write a myriad of WordPress events to syslog for integration with fail2ban.
6
  * Text Domain: wp-fail2ban
7
+ * Version: 4.4.0.8
8
  * Author: Charles Lecklider
9
  * Author URI: https://invis.net/
10
  * License: GPLv3