PluginProbe ʕ •ᴥ•ʔ
Paid Membership Plugin, Ecommerce, User Registration Form, Login Form, User Profile & Restrict Content – ProfilePress / 4.17.2
Paid Membership Plugin, Ecommerce, User Registration Form, Login Form, User Profile & Restrict Content – ProfilePress v4.17.2
4.17.2 4.17.1 4.17.0 4.16.19 4.16.18 4.16.17 4.16.16 trunk 1.0 1.0.1 1.0.2 1.1 1.1.1 1.1.2 1.1.3 1.1.4 1.1.5 1.1.5a 1.1.6 1.1.7 1.2 1.2.1 1.2.2 1.2.3 1.2.4 1.2.5 1.2.6 1.3 1.3.1 1.3.2 1.3.3 1.3.4 1.3.5 1.3.6 1.4 1.4.1 1.4.2 1.5 1.5.1 1.5.2 1.5.3 1.5.4 1.5.5 1.5.6 1.5.7 1.5.8 1.6 1.6.1 1.6.2 1.6.3 1.6.4 1.6.5 1.6.6 1.6.7 1.6.8 1.7 1.7.1 1.7.2 1.8 1.8.1 1.8.10 1.8.2 1.8.3 1.8.4 1.8.5 1.8.6 1.8.7 1.8.8 1.8.9 1.9 1.9.1 1.9.10 1.9.11 1.9.12 1.9.13 1.9.2 1.9.3 1.9.4 1.9.5 1.9.6 1.9.7 1.9.8 1.9.9 2.1.9 2.2.10 2.2.11 2.2.12 2.2.13 2.2.14 2.2.15 2.2.16 2.2.2 2.2.5 2.2.6 2.2.7 2.2.8 2.2.9 3.0 3.1 3.1.1 3.1.10 3.1.11 3.1.12 3.1.13 3.1.14 3.1.15 3.1.16 3.1.17 3.1.18 3.1.19 3.1.2 3.1.3 3.1.4 3.1.5 3.1.6 3.1.7 3.1.8 3.1.9 3.2.0 3.2.1 3.2.10 3.2.11 3.2.12 3.2.13 3.2.14 3.2.15 3.2.16 3.2.2 3.2.3 3.2.4 3.2.5 3.2.6 3.2.7 3.2.8 3.2.9 4.0.0 4.0.1 4.0.2 4.0.3 4.1.0 4.1.1 4.1.2 4.1.3 4.1.4 4.10.0 4.10.1 4.10.2 4.10.3 4.11.0 4.12.0 4.13.0 4.13.1 4.13.2 4.13.3 4.13.4 4.14.0 4.14.1 4.14.2 4.14.3 4.14.4 4.15.0 4.15.1 4.15.10 4.15.11 4.15.12 4.15.13 4.15.14 4.15.15 4.15.16 4.15.17 4.15.18 4.15.19 4.15.2 4.15.20 4.15.20.1 4.15.21 4.15.22 4.15.23 4.15.24 4.15.25 4.15.3 4.15.4 4.15.5 4.15.6 4.15.7 4.15.8 4.15.9 4.16.0 4.16.1 4.16.10 4.16.11 4.16.12 4.16.13 4.16.14 4.16.15 4.16.2 4.16.3 4.16.4 4.16.5 4.16.6 4.16.7 4.16.8 4.16.9 4.2.0 4.3.0 4.3.1 4.3.2 4.4.0 4.4.1 4.5.0 4.5.1 4.5.2 4.5.3 4.5.4 4.5.5 4.6.0 4.7.0 4.8.0 4.9.0
wp-user-avatar / src / Admin / SettingsPages / LicenseUpgrader.php
wp-user-avatar / src / Admin / SettingsPages Last commit date
DragDropBuilder 3 months ago EmailSettings 3 weeks ago Membership 3 weeks ago AbstractSettingsPage.php 2 years ago AddNewForm.php 1 year ago AdminFooter.php 4 years ago ExtensionsSettingsPage.php 1 year ago FormList.php 6 months ago Forms.php 1 year ago FuseWP.php 3 years ago GeneralSettings.php 11 months ago IDUserColumn.php 5 years ago LicenseUpgrader.php 5 days ago MailOptin.php 3 years ago MemberDirectories.php 1 year ago MembersDirectoryList.php 5 years ago ToolsSettingsPage.php 4 years ago index.php 3 years ago
LicenseUpgrader.php
478 lines
1 <?php
2
3 namespace ProfilePress\Core\Admin\SettingsPages;
4
5 use ProfilePress\Core\Classes\ExtensionManager;
6 use ProfilePress\Core\Classes\Installer\PluginSilentUpgrader;
7 use ProfilePress\Core\Classes\Installer\PluginSilentUpgraderSkin;
8 use ProfilePress\Custom_Settings_Page_Api;
9
10 class LicenseUpgrader
11 {
12 /** @var int Token validity in seconds (5 minutes) */
13 const TOKEN_EXPIRY_SECONDS = 300;
14
15 /** @var string Allowed download domain for plugin files */
16 const ALLOWED_DOWNLOAD_DOMAIN = 'profilepress.com';
17
18 public function __construct()
19 {
20 if ( ! ExtensionManager::is_premium()) {
21
22 add_filter('ppress_settings_page_submenus_tabs', [$this, 'add_menu']);
23 add_action('ppress_admin_settings_submenu_page_general_license', [$this, 'admin_page']);
24
25 add_action('ppress_register_menu_page_general_license', function () {
26
27 add_filter('ppress_general_settings_admin_page_title', function () {
28 return esc_html__('License', 'wp-user-avatar');
29 });
30 });
31
32 add_action('admin_enqueue_scripts', [$this, 'settings_enqueues']);
33
34 add_action('wp_ajax_ppress_connect_url', array($this, 'generate_url'));
35
36 add_action('wp_ajax_nopriv_ppress_connect_process', array($this, 'process'));
37 }
38 }
39
40 public function add_menu($tabs)
41 {
42 $tabs[-1] = ['parent' => 'general', 'id' => 'license', 'label' => esc_html__('License', 'wp-user-avatar')];
43
44 return $tabs;
45 }
46
47 public function admin_page()
48 {
49 $settings = [
50 [
51 'section_title' => '',
52 'disable_submit_button' => true,
53 'license_key' => [
54 'type' => 'arbitrary',
55 'data' => $this->admin_settings_page_callback()
56 ]
57 ]
58 ];
59
60 $instance = Custom_Settings_Page_Api::instance($settings, 'ppress_license', esc_html__('License', 'wp-user-avatar'));
61 $instance->remove_white_design();
62 $instance->remove_h2_header();
63 $instance->build(true);
64 }
65
66 public function admin_settings_page_callback()
67 {
68 $nonce = wp_create_nonce('ppress-connect-url');
69
70 ob_start();
71
72 ?>
73 <style>
74 .ppress-admin-wrap .wrap h2 {
75 display: none;
76 }
77
78 .ppress-admin .remove_white_styling #post-body-content .form-table th {
79 width: 200px !important;
80 }
81
82 .ppress-admin .remove_white_styling #post-body-content input[type=text] {
83 width: 25em !important;
84 }
85 </style>
86
87 <div class="ppress-lite-license-wrap">
88 <p style="font-size: 110%;">
89 <?php
90 esc_html_e(
91 'You\'re using ProfilePress Lite - no license needed. Enjoy! 😊',
92 'wp-user-avatar'
93 );
94 ?>
95 </p>
96
97 <p class="description" style="margin-bottom: 8px;">
98 <?php
99 echo wp_kses_post(
100 sprintf(
101 /* translators: %1$s Opening anchor tag, do not translate. %2$s Closing anchor tag, do not translate. */
102 __(
103 'Already purchased? Simply %1$sretrieve your license key%2$s and enter it below to connect with ProfilePress Pro.',
104 'wp-user-avatar'
105 ),
106 sprintf(
107 '<a href="%s" target="_blank" rel="noopener noreferrer">',
108 'https://profilepress.com/account/?utm_source=wp_dashboard&utm_medium=retrieve_license&utm_campaign=lite_license_page'
109 ),
110 '</a>'
111 )
112 );
113 ?>
114 </p>
115
116 <div class="ppress-license-field">
117 <input
118 type="text"
119 id="ppress-connect-license-key"
120 name="ppress-license-key"
121 value=""
122 class="regular-text"
123 style="line-height: 1; font-size: 1.15rem; padding: 10px;"
124 />
125
126 <button
127 class="button button-secondary ppress-license-button"
128 id="ppress-connect-license-submit"
129 data-connecting="<?php esc_attr_e('Connecting...', 'wp-user-avatar'); ?>"
130 data-connect="<?php esc_attr_e('Unlock Pro Features Now', 'wp-user-avatar'); ?>"
131 >
132 <?php esc_html_e('Unlock Pro Features Now', 'wp-user-avatar'); ?>
133 </button>
134
135 <input type="hidden" name="ppress-action" value="ppress-connect"/>
136 <input type="hidden" id="ppress-connect-license-nonce" name="ppress-connect-license-nonce" value="<?php echo esc_attr($nonce); ?>"/>
137 </div>
138
139 <div id="ppress-connect-license-feedback" class="ppress-license-message"></div>
140
141 <div class="ppress-settings-upgrade">
142 <div class="ppress-settings-upgrade__inner">
143 <span class="dashicons dashicons-unlock" style="font-size: 40px; width: 40px; height: 50px;"></span>
144 <h3>
145 <?php esc_html_e('Unlock Powerful Pro Features', 'wp-user-avatar'); ?>
146 </h3>
147
148 <ul>
149 <li>
150 <div class="dashicons dashicons-yes"></div>
151 <?php esc_html_e('No extra 2% Stripe fee', 'wp-user-avatar'); ?>
152 </li>
153 <li>
154 <div class="dashicons dashicons-yes"></div>
155 <a href="https://profilepress.com/addons/paypal/?utm_source=wp_dashboard&utm_medium=retrieve_license&utm_campaign=lite_license_page" target="_blank" rel="noopener noreferrer">
156 <?php esc_html_e('Collect PayPal payments', 'wp-user-avatar'); ?>
157 </a>
158 </li>
159 <li>
160 <div class="dashicons dashicons-yes"></div>
161 <a href="https://profilepress.com/addons/?utm_source=wp_dashboard&utm_medium=retrieve_license&utm_campaign=lite_license_page" target="_blank" rel="noopener noreferrer">
162 <?php esc_html_e('Mollie & Razorpay gateways', 'wp-user-avatar'); ?>
163 </a>
164 </li>
165 <li>
166 <div class="dashicons dashicons-yes"></div>
167 <?php esc_html_e('Premium form & profile themes', 'wp-user-avatar'); ?>
168 </li>
169 <li>
170 <div class="dashicons dashicons-yes"></div>
171 <?php esc_html_e('Premium directory themes', 'wp-user-avatar'); ?>
172 </li>
173 <li>
174 <div class="dashicons dashicons-yes"></div>
175 <a href="https://profilepress.com/article/drag-drop-advanced-shortcode-builders/?utm_source=wp_dashboard&utm_medium=retrieve_license&utm_campaign=lite_license_page" target="_blank" rel="noopener noreferrer">
176 <?php esc_html_e('Advanced shortcode builder', 'wp-user-avatar'); ?>
177 </a>
178 </li>
179 <li>
180 <div class="dashicons dashicons-yes"></div>
181 <a href="https://profilepress.com/addons/custom-fields/?utm_source=wp_dashboard&utm_medium=retrieve_license&utm_campaign=lite_license_page" target="_blank" rel="noopener noreferrer">
182 <?php esc_html_e('Custom Fields', 'wp-user-avatar'); ?>
183 </a>
184 </li>
185 <li>
186 <div class="dashicons dashicons-yes"></div>
187 <a href="https://profilepress.com/addons/social-login/?utm_source=wp_dashboard&utm_medium=retrieve_license&utm_campaign=lite_license_page" target="_blank" rel="noopener noreferrer">
188 <?php esc_html_e('Social Login', 'wp-user-avatar'); ?>
189 </a>
190 </li>
191 <li>
192 <div class="dashicons dashicons-yes"></div>
193 <a href="https://profilepress.com/addons/metered-paywall/?utm_source=wp_dashboard&utm_medium=retrieve_license&utm_campaign=lite_license_page" target="_blank" rel="noopener noreferrer">
194 <?php esc_html_e('Metered Paywall', 'wp-user-avatar'); ?>
195 </a>
196 </li>
197 <li>
198 <div class="dashicons dashicons-yes"></div>
199 <a href="https://profilepress.com/addons/user-moderation/?utm_source=wp_dashboard&utm_medium=retrieve_license&utm_campaign=lite_license_page" target="_blank" rel="noopener noreferrer">
200 <?php esc_html_e('User Moderation', 'wp-user-avatar'); ?>
201 </a>
202 </li>
203 <li>
204 <div class="dashicons dashicons-yes"></div>
205 <a href="https://profilepress.com/addons/passwordless-login/?utm_source=wp_dashboard&utm_medium=retrieve_license&utm_campaign=lite_license_page" target="_blank" rel="noopener noreferrer">
206 <?php esc_html_e('Passwordless Login', 'wp-user-avatar'); ?>
207 </a>
208 </li>
209 <li>
210 <div class="dashicons dashicons-yes"></div>
211 <a href="https://profilepress.com/addons/?utm_source=wp_dashboard&utm_medium=retrieve_license&utm_campaign=lite_license_page" target="_blank" rel="noopener noreferrer">
212 <?php esc_html_e('And more addons', 'wp-user-avatar'); ?>
213 </a>
214 </li>
215 </ul>
216
217 <a href="https://profilepress.com/pricing/?discount=10PPOFF&utm_source=wp_dashboard&utm_medium=retrieve_license&utm_campaign=lite_license_page" class="button button-primary button-large ppress-upgrade-btn ppress-upgrade-btn-large" target="_blank" rel="noopener noreferrer">
218 <?php esc_html_e('Upgrade to ProfilePress Pro', 'wp-user-avatar'); ?>
219 </a>
220 </div>
221
222 <div class="ppress-upgrade-btn-subtext">
223 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24" role="img" aria-hidden="true" focusable="false">
224 <path d="M16.7 7.1l-6.3 8.5-3.3-2.5-.9 1.2 4.5 3.4L17.9 8z"></path>
225 </svg>
226
227 <?php
228 echo wp_kses(
229 sprintf(
230 /* translators: %1$s Opening anchor tag, do not translate. %2$s Closing anchor tag, do not translate. */
231 __(
232 '<strong>Bonus</strong>: Loyal ProfilePress Lite users get <u>10%% off</u> regular price, automatically applied at checkout. %1$sUpgrade to Pro →%2$s',
233 'wp-user-avatar'
234 ),
235 sprintf(
236 '<a href="%s" rel="noopener noreferrer" target="_blank">',
237 'https://profilepress.com/pricing/?discount=10PPOFF&utm_source=wp_dashboard&utm_medium=retrieve_license&utm_campaign=lite_license_page'
238 ),
239 '</a>'
240 ),
241 array(
242 'a' => array(
243 'href' => true,
244 'rel' => true,
245 'target' => true,
246 ),
247 'strong' => array(),
248 'u' => array(),
249 )
250 );
251 ?>
252 </div>
253 </div>
254 </div>
255 <?php
256 return ob_get_clean();
257 }
258
259 public function settings_enqueues()
260 {
261 wp_enqueue_script(
262 'ppress-license-connect',
263 PPRESS_ASSETS_URL . "/js/admin/license.js",
264 ['jquery'],
265 PPRESS_VERSION_NUMBER,
266 true
267 );
268 }
269
270 public function generate_url()
271 {
272 check_ajax_referer('ppress-connect-url', 'nonce');
273
274 // Check for permissions.
275 if ( ! current_user_can('install_plugins')) {
276 wp_send_json_error(['message' => esc_html__('You are not allowed to install plugins.', 'wp-user-avatar')]);
277 }
278
279 $key = ! empty($_POST['key']) ? sanitize_text_field(wp_unslash($_POST['key'])) : '';
280
281 if (empty($key)) {
282 wp_send_json_error(['message' => esc_html__('Please enter your license key to connect.', 'wp-user-avatar')]);
283 }
284
285 if (ExtensionManager::is_premium()) {
286 wp_send_json_error(['message' => esc_html__('Only the Lite version can be upgraded.', 'wp-user-avatar')]);
287 }
288
289 $active = activate_plugin('profilepress-pro/profilepress-pro.php', false, false, true);
290
291 if ( ! is_wp_error($active)) {
292
293 update_option('ppress_license_key', $key);
294
295 wp_send_json_success([
296 'message' => \esc_html__('You already have ProfilePress Pro installed! Activating it now', 'wp-user-avatar'),
297 'reload' => true
298 ]);
299 }
300
301 try {
302 // Use cryptographically secure random bytes instead of wp_rand()
303 $oth = bin2hex(random_bytes(32));
304 } catch (\Exception $e) {
305 wp_send_json_error(['message' => esc_html__('No sources of randomness found on the server.', 'wp-user-avatar')]);
306 }
307
308 // Store token with timestamp for expiration and user verification
309 update_option('ppress_connect_token', [
310 'token' => $oth,
311 'created_at' => time()
312 ]);
313 update_option('ppress_license_key', $key);
314
315 $version = PPRESS_VERSION_NUMBER;
316 $endpoint = admin_url('admin-ajax.php');
317 $redirect = PPRESS_SETTINGS_SETTING_GENERAL_PAGE;
318 $url = add_query_arg(
319 [
320 'key' => $key,
321 'oth' => $oth,
322 'endpoint' => $endpoint,
323 'version' => $version,
324 'siteurl' => \admin_url(),
325 'homeurl' => \home_url(),
326 'redirect' => rawurldecode(base64_encode($redirect)), // phpcs:ignore
327 'v' => 1,
328 ],
329 'https://upgrade.profilepress.com'
330 );
331
332 wp_send_json_success(['url' => $url]);
333 }
334
335 public function process()
336 {
337 $error = wp_kses(
338 sprintf(
339 /* translators: %1$s Opening anchor tag, do not translate. %2$s Closing anchor tag, do not translate. */
340 __(
341 'Oops! We could not automatically install an upgrade. Please download the plugin from profilepress.com and install it manually.',
342 'wp-user-avatar'
343 )
344 ),
345 [
346 'a' => [
347 'target' => true,
348 'href' => true,
349 ],
350 ]
351 );
352
353 $post_oth = ! empty($_REQUEST['oth']) ? sanitize_text_field($_REQUEST['oth']) : '';
354 $post_url = ! empty($_REQUEST['file']) ? esc_url_raw($_REQUEST['file']) : '';
355
356 $license = get_option('ppress_license_key', '');
357
358 if (empty($post_oth) || empty($post_url)) {
359 wp_send_json_error(['message' => $error, 'code_err' => '1']);
360 }
361
362 // Validate URL is from allowed domain
363 $parsed_url = wp_parse_url($post_url);
364 $url_host = isset($parsed_url['host']) ? strtolower($parsed_url['host']) : '';
365
366 // Allow profilepress.com and subdomains (e.g., downloads.profilepress.com)
367 if ($url_host !== self::ALLOWED_DOWNLOAD_DOMAIN &&
368 ! preg_match('/\.' . preg_quote(self::ALLOWED_DOWNLOAD_DOMAIN, '/') . '$/', $url_host)) {
369 wp_send_json_error(['message' => $error, 'code_err' => 'invalid_domain']);
370 }
371
372 // Verify URL uses HTTPS
373 if ( ! isset($parsed_url['scheme']) || strtolower($parsed_url['scheme']) !== 'https') {
374 wp_send_json_error(['message' => $error, 'code_err' => 'insecure_url']);
375 }
376
377 $token_data = get_option('ppress_connect_token');
378
379 // Always delete token on any attempt (success or failure) to prevent brute-force
380 delete_option('ppress_connect_token');
381
382 if (empty($token_data) || ! is_array($token_data)) {
383 wp_send_json_error(['message' => $error, 'code_err' => '2']);
384 }
385
386 $stored_token = $token_data['token'] ?? '';
387 $created_at = isset($token_data['created_at']) ? (int) $token_data['created_at'] : 0;
388
389 // Verify token hasn't expired
390 if ((time() - $created_at) > self::TOKEN_EXPIRY_SECONDS) {
391 wp_send_json_error(['message' => esc_html__('The connection token has expired. Please try again.', 'wp-user-avatar'), 'code_err' => 'token_expired']);
392 }
393
394 if ( ! hash_equals($stored_token, $post_oth)) {
395 wp_send_json_error(['message' => $error, 'code_err' => '3']);
396 }
397
398 // Set the current screen to avoid undefined notices.
399 set_current_screen('profilepress_page_ppress-config');
400
401 $url = PPRESS_SETTINGS_SETTING_GENERAL_PAGE;
402
403 // Verify pro not activated.
404 if (ExtensionManager::is_premium()) {
405 wp_send_json_success(esc_html__('Plugin installed & activated.', 'wp-user-avatar'));
406 }
407
408 // Verify pro not installed.
409 $active = activate_plugin('profilepress-pro/profilepress-pro.php', $url, false, true);
410
411 if ( ! is_wp_error($active)) {
412
413 wp_send_json_success([
414 'message' => esc_html__('Plugin installed & activated.', 'wp-user-avatar'),
415 'code_err' => '3.5'
416 ]);
417 }
418
419 $creds = request_filesystem_credentials($url, '', false, false, null);
420
421 // Check for file system permissions.
422 if (false === $creds || ! \WP_Filesystem($creds)) {
423 wp_send_json_error(['message' => $error, 'code_err' => '4']);
424 }
425
426 /*
427 * We do not need any extra credentials if we have gotten this far, so let's install the plugin.
428 */
429
430 // Do not allow WordPress to search/download translations, as this will break JS output.
431 remove_action('upgrader_process_complete', ['Language_Pack_Upgrader', 'async_upgrade'], 20);
432
433 // Create the plugin upgrader with our custom skin.
434 $installer = new PluginSilentUpgrader(new PluginSilentUpgraderSkin());
435
436 // Error check.
437 if ( ! method_exists($installer, 'install')) {
438 wp_send_json_error(['message' => $error, 'code_err' => '5']);
439 }
440
441 if (empty($license)) {
442 wp_send_json_error([
443 'message' => esc_html__('You are not licensed.', 'wp-user-avatar'),
444 'code_err' => '6'
445 ]);
446 }
447
448 $installer->install($post_url);
449
450 // Flush the cache and return the newly installed plugin basename.
451 wp_cache_flush();
452
453 $plugin_basename = $installer->plugin_info();
454
455 if ($plugin_basename) {
456
457 // Activate the plugin silently.
458 $activated = activate_plugin($plugin_basename, '', false, true);
459
460 if ( ! is_wp_error($activated)) {
461 wp_send_json_success(esc_html__('Plugin installed & activated.', 'wp-user-avatar'));
462 }
463 }
464
465 wp_send_json_error(['message' => $error, 'code_err' => '7']);
466 }
467
468 public static function get_instance()
469 {
470 static $instance = null;
471
472 if (is_null($instance)) {
473 $instance = new self();
474 }
475
476 return $instance;
477 }
478 }